# Multiprecision rationals¶

New in version 0.3.

#include <mp++/rational.hpp>

## The rational class¶

template<std::size_t SSize>
class rational

Multiprecision rational class.

This class represents arbitrary-precision rationals. Internally, the class stores a pair of integers with static size SSize as the numerator and denominator. Rational numbers are represented in the usual canonical form:

• numerator and denominator are coprime,

• the denominator is always strictly positive.

This class has the look and feel of a C++ builtin type: it can interact with most of C++’s integral and floating-point primitive types (see the CppInteroperable concept for the full list) and with integers with static size SSize, and it provides overloaded operators. Differently from the builtin types, however, this class does not allow any implicit conversion to/from other types (apart from bool): construction from and conversion to primitive types must always be requested explicitly. As a side effect, syntax such as

rational<1> q = 5;
int m = q;


will not work, and direct initialization should be used instead:

rational<1> q{5};
int m{q};


Most of the functionality is exposed via plain functions, with the general convention that the functions are named after the corresponding GMP functions minus the leading mpq_ prefix. For instance, the GMP call

mpq_add(rop,a,b);


that writes the result of a + b into rop becomes simply

add(rop,a,b);


where the add() function is resolved via argument-dependent lookup. Function calls with overlapping arguments are allowed, unless noted otherwise. In a similar way to the integer class, various convenience overloads are provided for the same functionality. For instance, here are three possible ways of computing the absolute value:

rational<1> q1, q2, q{-5};
abs(q1,q);   // Binary abs(): computes and stores the absolute value
// of q into q1.
q2 = abs(q); // Unary abs(): returns the absolute value of q, which is
// then assigned to q2.
q.abs();     // Member function abs(): replaces the value of q with its
// absolute value.


Various overloaded operators are provided. For the common arithmetic operations (+, -, * and /), the type promotion rules are a natural extension of the corresponding rules for native C++ types: if the other argument is a C++ integral or an integer, the result will be of type rational, if the other argument is a C++ floating-point the result will be of the same floating-point type. For example:

rational<1> q1{1}, q2{2};
integer<1> n{2};
auto res1 = q1 + q2; // res1 is a rational
auto res2 = q1 * 2; // res2 is a rational
auto res3 = q1 * n; // res3 is a rational
auto res4 = 2 - q2; // res4 is a rational
auto res5 = q1 / 2.f; // res5 is a float
auto res6 = 12. / q1; // res6 is a double


The relational operators, ==, !=, <, >, <= and >= will promote the arguments to a common type before comparing them. The promotion rules are the same as in the arithmetic operators (that is, both arguments are promoted to rational if no floating-point types are involved, otherwise they are promoted to the type of the floating-point argument).

The rational class allows to access and manipulate directly the numerator and denominator via the get_num(), get_den(), _get_num() and _get_den() methods, so that it is possible to use integer functions directly on numerator and denominator. The mutable getters’ names _get_num() and _get_den() are prefixed with an underscore _ to highlight their potentially dangerous nature: it is the user’s responsibility to ensure that the canonical form of the rational is preserved after altering the numerator and/or the denominator via the mutable getters.

Public Types

typedef integer<SSize> int_t

Underlying integral type.

This is the integer type used for the representation of numerator and denominator.

Public Functions

rational()

Default constructor.

The default constructor will initialize this to 0 (represented as 0/1).

rational(const rational&)

Defaulted copy constructor.

rational(rational &&other)

Move constructor.

The move constructor will leave other in an unspecified but valid state.

Parameters
• other: the construction argument.

template<RationalCvrInteroperable<SSize> T>
rational(T &&x)

Generic constructor.

This constructor will initialize a rational with the value x. The construction will fail if x is a non-finite floating-point value.

Parameters
• x: the value that will be used to initialize this.

Exceptions
• std::domain_error: if x is a non-finite floating-point value.

template<RationalCvrIntegralInteroperable<SSize> T, RationalCvrIntegralInteroperable<SSize> U>
rational(T &&n, U &&d, bool make_canonical = true)

Constructor from numerator and denominator.

This constructor is enabled only if both T and U satisfy the RationalCvrIntegralInteroperable concept. The input value n will be used to initialise the numerator, while d will be used to initialise the denominator. If make_canonical is true (the default), then canonicalise() will be called after the construction of numerator and denominator.

Warning

If this constructor is called with make_canonical set to false, it will be the user’s responsibility to ensure that this is canonicalised before using it with other mp++ functions. Failure to do so will result in undefined behaviour.

Parameters
• n: the numerator.

• d: the denominator.

• make_canonical: if true, the rational will be canonicalised after the construction of numerator and denominator.

Exceptions
• zero_division_error: if the denominator is zero.

template<StringType T>
rational(const T &s, int base = 10)

Constructor from string.

This constructor will initialize this from the StringType s, which must represent a rational value in base base. The expected format is either a numerator-denominator pair separated by the division operator /, or just a numerator (in which case the denominator will be set to one). The format for numerator and denominator is described in the documentation of the constructor from string of integer.

Parameters
• s: the input string.

• base: the base used in the string representation.

Exceptions
• zero_division_error: if the denominator is zero.

• unspecified: any exception thrown by the string constructor of mppp::integer, or by memory errors in standard containers.

rational(const char *begin, const char *end, int base = 10)

Constructor from range of characters.

This constructor will initialise this from the content of the input half-open range, which is interpreted as the string representation of a rational in base base.

Internally, the constructor will copy the content of the range to a local buffer, add a string terminator, and invoke the constructor from string.

Parameters
• begin: the begin of the input range.

• end: the end of the input range.

• base: the base used in the string representation.

Exceptions
• unspecified: any exception thrown by the constructor from string, or by memory errors in standard containers.

rational(const mpz_t n)

Constructor from mpz_t.

This constructor will initialise the numerator of this with the input GMP integer n, and the denominator to 1.

Warning

It is the user’s responsibility to ensure that n has been correctly initialized. Calling this constructor with an uninitialized n results in undefined behaviour.

Parameters
• n: the input GMP integer.

rational(const mpq_t q)

Copy constructor from mpq_t.

This constructor will initialise the numerator and denominator of this with those of the GMP rational q.

Warning

It is the user’s responsibility to ensure that q has been correctly initialized. Calling this constructor with an uninitialized q results in undefined behaviour.

This constructor will not canonicalise this: numerator and denominator are constructed as-is from q.

Parameters
• q: the input GMP rational.

rational(mpq_t &&q)

Move constructor from mpq_t.

This constructor will move the numerator and denominator of the GMP rational q into this.

Warning

It is the user’s responsibility to ensure that q has been correctly initialized. Calling this constructor with an uninitialized q results in undefined behaviour.

This constructor will not canonicalise this: numerator and denominator are constructed as-is from q.

The user must ensure that, after construction, mpq_clear() is never called on q: the resources previously owned by q are now owned by this, which will take care of releasing them when the destructor is called.

Note

Due to a compiler bug, this constructor is not available on Microsoft Visual Studio.

Parameters
• q: the input GMP rational.

rational &operator=(const rational&)

Defaulted copy-assignment operator.

Return

a reference to this.

rational &operator=(rational &&other)

Defaulted move assignment operator.

After the assignment, other is left in an unspecified but valid state.

Return

a reference to this.

Parameters
• other: the assignment argument.

template<RationalCvrInteroperable<SSize> T>
rational &operator=(T &&x)

Generic assignment operator.

This operator will assign x to this.

Return

a reference to this.

Parameters
• x: the assignment argument.

Exceptions
• unspecified: any exception thrown by the generic constructor.

template<StringType T>
rational &operator=(const T &s)

Assignment from string.

The body of this operator is equivalent to:

return *this = rational{s};


That is, a temporary rational is constructed from s and it is then move-assigned to this.

Return

a reference to this.

Parameters
• s: the string that will be used for the assignment.

Exceptions
• unspecified: any exception thrown by the constructor from string.

rational &operator=(const mpz_t n)

Assignment from mpz_t.

This assignment operator will copy into the numerator of this the value of the GMP integer n, and it will set the denominator to 1 via mppp::integer::set_one().

Warning

It is the user’s responsibility to ensure that n has been correctly initialized. Calling this operator with an uninitialized n results in undefined behaviour.

No aliasing is allowed: the data in n must be completely distinct from the data in this (e.g., if n is an mpz_view of the numerator of this then it might point to internal data of this, and the behaviour of this operator will thus be undefined).

Return

a reference to this.

Parameters
• n: the input GMP integer.

rational &operator=(const mpq_t q)

Copy assignment from mpq_t.

This assignment operator will copy into this the value of the GMP rational q.

Warning

It is the user’s responsibility to ensure that q has been correctly initialized. Calling this operator with an uninitialized q results in undefined behaviour.

This operator will not canonicalise the assigned value: numerator and denominator are assigned as-is from q.

No aliasing is allowed: the data in q must be completely distinct from the data in this.

Return

a reference to this.

Parameters
• q: the input GMP rational.

rational &operator=(mpq_t &&q)

Move assignment from mpq_t.

This assignment operator will move the GMP rational q into this.

Warning

It is the user’s responsibility to ensure that q has been correctly initialized. Calling this operator with an uninitialized q results in undefined behaviour.

This operator will not canonicalise the assigned value: numerator and denominator are assigned as-is from q.

No aliasing is allowed: the data in q must be completely distinct from the data in this.

The user must ensure that, after the assignment, mpq_clear() is never called on q: the resources previously owned by q are now owned by this, which will take care of releasing them when the destructor is called.

Note

Due to a compiler bug, this operator is not available on Microsoft Visual Studio.

Return

a reference to this.

Parameters
• q: the input GMP rational.

std::string to_string(int base = 10) const

Convert to string.

This operator will return a string representation of this in base base. The string format consists of the numerator, followed by the division operator / and the denominator, but only if the denominator is not unitary. Otherwise, only the numerator will be represented in the returned string.

Return

a string representation for this.

Parameters
• base: the desired base for the string representation.

Exceptions

template<RationalInteroperable<SSize> T>
operator T() const

Generic conversion operator.

This operator will convert this to a RationalInteroperable type. Conversion to bool yields false if this is zero, true otherwise. Conversion to other integral types and to int_t yields the result of the truncated division of the numerator by the denominator, if representable by the target RationalInteroperable type. Conversion to floating-point types might yield inexact values and infinities.

Return

this converted to the target type.

Exceptions
• std::overflow_error: if the target type is an integral type and the value of this cannot be represented by it.

template<RationalInteroperable<SSize> T>
bool get(T &rop) const

Generic conversion method.

This method, similarly to the conversion operator, will convert this to a RationalInteroperable type, storing the result of the conversion into rop. Differently from the conversion operator, this method does not raise any exception: if the conversion is successful, the method will return true, otherwise the method will return false. If the conversion fails, rop will not be altered.

Return

true if the conversion succeeded, false otherwise. The conversion can fail only if rop is a C++ integral which cannot represent the truncated value of this.

Parameters
• rop: the variable which will store the result of the conversion.

const int_t &get_num() const

Const numerator getter.

Return

a const reference to the numerator.

const int_t &get_den() const

Const denominator getter.

Return

a const reference to the denominator.

int_t &_get_num()

Mutable numerator getter.

Warning

It is the user’s responsibility to ensure that, after changing the numerator via this getter, the rational is kept in canonical form.

Return

a mutable reference to the numerator.

int_t &_get_den()

Mutable denominator getter.

Warning

It is the user’s responsibility to ensure that, after changing the denominator via this getter, the rational is kept in canonical form.

Return

a mutable reference to the denominator.

rational &canonicalise()

Canonicalise.

This method will put this in canonical form. In particular, this method will make sure that:

• the numerator and denominator are coprime (dividing them by their GCD, if necessary),

• the denominator is strictly positive.

In general, it is not necessary to call explicitly this method, as the public API of rational ensures that rationals are kept in canonical form. Calling this method, however, might be necessary if the numerator and/or denominator are modified manually, or when constructing/assigning from non-canonical mpq_t values.

Warning

Calling this method with on a rational with null denominator will result in undefined behaviour.

Return

a reference to this.

bool is_canonical() const

Check canonical form.

Return

true if this is the canonical form for rational numbers, false otherwise.

int sgn() const

Sign.

Return

0 if this is zero, 1 if this is positive, -1 if this is negative.

rational &neg()

Negate in-place.

This method will set this to -this.

Return

a reference to this.

rational &abs()

In-place absolute value.

This method will set this to its absolute value.

Return

a reference to this.

rational &inv()

In-place inversion.

This method will set this to its inverse.

Return

a reference to this.

Exceptions
• zero_division_error: if this is zero.

bool is_zero() const

Test if the value is zero.

Return

true if the value represented by this is 0, false otherwise.

bool is_one() const

Test if the value is one.

Return

true if the value represented by this is 1, false otherwise.

bool is_negative_one() const

Test if the value is minus one.

Return

true if the value represented by this is -1, false otherwise.

Public Static Attributes

constexpr std::size_t ssize = SSize

Alias for the template parameter SSize.

## Concepts¶

template<typename T, std::size_t SSize>
concept mppp::RationalInteroperable

This concept is satisfied if the type T can interoperate with a rational with static size SSize. Specifically, this concept will be true if T satisfies CppInteroperable or it is an integer with static size SSize.

A corresponding boolean type trait called is_rational_interoperable is also available (even if the compiler does not support concepts).

template<typename T, std::size_t SSize>
concept mppp::RationalCvrInteroperable

This concept is satisfied if the type T, after the removal of reference and cv qualifiers, satisfies RationalInteroperable.

template<typename T, std::size_t SSize>
concept mppp::RationalIntegralInteroperable

This concept is satisfied if either:

A corresponding boolean type trait called is_rational_integral_interoperable is also available (even if the compiler does not support concepts).

template<typename T, std::size_t SSize>
concept mppp::RationalCvrIntegralInteroperable

This concept is satisfied if the type T, after the removal of reference and cv qualifiers, satisfies RationalIntegralInteroperable.

template<typename T, typename U>
concept mppp::RationalOpTypes

This concept is satisfied if the types T and U are suitable for use in the generic binary operators and functions involving rational. Specifically, the concept will be true if either:

• T and U are both rational with the same static size SSize, or

• one type is a rational and the other is a RationalInteroperable type.

A corresponding boolean type trait called are_rational_op_types is also available (even if the compiler does not support concepts).

## Functions¶

Much of the functionality of the rational class is exposed via plain functions. These functions mimic the GMP API where appropriate, but a variety of convenience/generic overloads is provided as well.

### Assignment¶

template<std::size_t SSize>
void mppp::swap(mppp::rational<SSize> &q1, mppp::rational<SSize> &q2) noexcept

New in version 0.15.

Swap.

This function will efficiently swap the values of q1 and q2.

Parameters
• q1 – the first argument.

• q2 – the second argument.

### Conversion¶

template<typename T, std::size_t SSize>requires RationalInteroperable<T, SSize> bool mppp::get(T & rop, const rational< SSize > & q)

Generic conversion function for rational.

This function will convert the input rational q to a RationalInteroperable type, storing the result of the conversion into rop. If the conversion is successful, the function will return true, otherwise the function will return false. If the conversion fails, rop will not be altered.

Return

true if the conversion succeeded, false otherwise. The conversion can fail only if rop is a C++ integral which cannot represent the truncated value of q.

Parameters
• rop: the variable which will store the result of the conversion.

• q: the input rational.

### Arithmetic¶

template<std::size_t SSize>
rational<SSize> &mppp::add(rational<SSize> &rop, const rational<SSize> &op1, const rational<SSize> &op2)

This function will set rop to op1 + op2.

Return

a reference to rop.

Parameters
• rop: the return value.

• op1: the first argument.

• op2: the second argument.

template<std::size_t SSize>
rational<SSize> &mppp::sub(rational<SSize> &rop, const rational<SSize> &op1, const rational<SSize> &op2)

Ternary subtraction.

This function will set rop to op1 - op2.

Return

a reference to rop.

Parameters
• rop: the return value.

• op1: the first argument.

• op2: the second argument.

template<std::size_t SSize>
rational<SSize> &mppp::mul(rational<SSize> &rop, const rational<SSize> &op1, const rational<SSize> &op2)

Ternary multiplication.

This function will set rop to op1 * op2.

Return

a reference to rop.

Parameters
• rop: the return value.

• op1: the first argument.

• op2: the second argument.

template<std::size_t SSize>
rational<SSize> &mppp::div(rational<SSize> &rop, const rational<SSize> &op1, const rational<SSize> &op2)

Ternary division.

This function will set rop to op1 / op2.

Return

a reference to rop.

Parameters
• rop: the return value.

• op1: the first argument.

• op2: the second argument.

Exceptions
• zero_division_error: if op2 is zero.

template<std::size_t SSize>
rational<SSize> &mppp::neg(rational<SSize> &rop, const rational<SSize> &q)

Binary negation.

This method will set rop to -q.

Return

a reference to rop.

Parameters
• rop: the return value.

• q: the rational that will be negated.

template<std::size_t SSize>
rational<SSize> mppp::neg(const rational<SSize> &q)

Unary negation.

Return

-q.

Parameters
• q: the rational that will be negated.

template<std::size_t SSize>
rational<SSize> &mppp::abs(rational<SSize> &rop, const rational<SSize> &q)

Binary absolute value.

This function will set rop to the absolute value of q.

Return

a reference to rop.

Parameters
• rop: the return value.

• q: the argument.

template<std::size_t SSize>
rational<SSize> mppp::abs(const rational<SSize> &q)

Unary absolute value.

Return

the absolute value of q.

Parameters
• q: the argument.

template<std::size_t SSize>
rational<SSize> &mppp::inv(rational<SSize> &rop, const rational<SSize> &q)

Binary inversion.

This function will set rop to the inverse of q.

Return

a reference to rop.

Parameters
• rop: the return value.

• q: the argument.

Exceptions

template<std::size_t SSize>
rational<SSize> mppp::inv(const rational<SSize> &q)

Unary inversion.

Return

the inverse of q.

Parameters
• q: the argument.

Exceptions

### Comparison¶

template<std::size_t SSize>
int mppp::cmp(const rational<SSize> &op1, const rational<SSize> &op2)

Comparison function for rationals.

Return

0 if op1 == op2, a negative value if op1 < op2, a positive value if op1 > op2.

Parameters
• op1: first argument.

• op2: second argument.

template<std::size_t SSize>
int mppp::cmp(const rational<SSize> &op1, const integer<SSize> &op2)

Comparison function for rational/integer arguments.

Return

0 if op1 == op2, a negative value if op1 < op2, a positive value if op1 > op2.

Parameters
• op1: first argument.

• op2: second argument.

template<std::size_t SSize>
int mppp::cmp(const integer<SSize> &op1, const rational<SSize> &op2)

Comparison function for integer/rational arguments.

Return

0 if op1 == op2, a negative value if op1 < op2, a positive value if op1 > op2.

Parameters
• op1: first argument.

• op2: second argument.

template<std::size_t SSize>
int mppp::sgn(const rational<SSize> &q)

Sign function.

Return

0 if q is zero, 1 if q is positive, -1 if q is negative.

Parameters
• q: the rational whose sign will be computed.

template<std::size_t SSize>
bool mppp::is_one(const rational<SSize> &q)

Test if a rational is one.

Return

true if q is 1, false otherwise.

Parameters
• q: the rational to be tested.

template<std::size_t SSize>
bool mppp::is_negative_one(const rational<SSize> &q)

Test if a rational is minus one.

Return

true if q is -1, false otherwise.

Parameters
• q: the rational to be tested.

template<std::size_t SSize>
bool mppp::is_zero(const rational<SSize> &q)

Test if a rational is zero.

Return

true if q is 0, false otherwise.

Parameters
• q: the rational to be tested.

### Number theoretic functions¶

New in version 0.8.

template<std::size_t SSize, typename T>requires RationalIntegralInteroperable<T, SSize> rational<SSize> mppp::binomial(const rational< SSize > & x, const T & y)

Binomial coefficient for rational.

This function will compute the binomial coefficient $${x \choose y}$$. If x represents an integral value, the calculation is forwarded to the implementation of the binomial coefficient for integer. Otherwise, an implementation based on the falling factorial is employed.

Return

$${x \choose y}$$.

Parameters
• x: the top value.

• y: the bottom value.

Exceptions
• unspecified: any exception thrown by the implementation of the binomial coefficient for integer.

### Exponentiation¶

template<typename T, typename U>requires RationalOpTypes<T, U> auto mppp::pow(const T & base, const U & exp)

Binary exponentiation.

This function will raise base to the power exp, and return the result. If one of the arguments is a floating-point value, then the result will be computed via std::pow() and it will also be a floating-point value. Otherwise, the result will be a rational.

When floating-point types are not involved, the implementation is based on the integral exponentiation of numerator and denominator. Thus, if exp is a rational value, the exponentiation will be successful only in a few special cases (e.g., unitary base, zero exponent, etc.).

Return

base**exp.

Parameters
• base: the base.

• exp: the exponent.

Exceptions
• zero_division_error: if floating-point types are not involved, base is zero and exp is negative.

• std::domain_error: if floating-point types are not involved and exp is a rational value (except in a handful of special cases).

### Input/Output¶

template<std::size_t SSize>
std::ostream &mppp::operator<<(std::ostream &os, const mppp::rational<SSize> &q)

Stream insertion operator.

This function will direct to the output stream os the input rational q.

Parameters
• os – the output stream.

• q – the input rational.

Returns

a reference to os.

Throws
• std::overflow_error – in case of (unlikely) overflow errors.

• unspecified – any exception raised by the public interface of std::ostream or by memory allocation errors.

### Other¶

template<std::size_t SSize>
rational<SSize> &mppp::canonicalise(rational<SSize> &rop)

Canonicalise.

This function will put rop in canonical form. Internally, this function will employ mppp::rational::canonicalise().

Return

a reference to rop.

Parameters
• rop: the rational that will be canonicalised.

template<std::size_t SSize>
std::size_t mppp::hash(const rational<SSize> &q)

Hash value.

This function will return a hash value for q.

A specialisation of the standard std::hash functor is also provided, so that it is possible to use rational in standard unordered associative containers out of the box.

Return

a hash value for q.

Parameters
• q: the rational whose hash value will be computed.

## Mathematical operators¶

Overloaded operators are provided for convenience. Their interface is generic, and their implementation is typically built on top of basic functions.

template<std::size_t SSize>
rational<SSize> mppp::operator+(const rational<SSize> &q)

Identity operator.

Return

a copy of q.

Parameters
• q: the rational that will be copied.

template<typename T, typename U>requires RationalOpTypes<T, U> auto mppp::operator+(const T & op1, const U & op2)

The return type is determined as follows:

• if the non-rational argument is a floating-point type F, then the type of the result is F; otherwise,

• the type of the result is a rational.

Return

op1 + op2.

Parameters
• op1: the first summand.

• op2: the second summand.

template<typename T, typename U>requires RationalOpTypes<T, U> T& mppp::operator+=(T & rop, const U & op)

Return

a reference to rop.

Parameters
• rop: the augend.

• op: the addend.

Exceptions
• unspecified: any exception thrown by the assignment of a floating-point value to rop or by the conversion operator of rational.

template<std::size_t SSize>
rational<SSize> &mppp::operator++(rational<SSize> &q)

Prefix increment for rational.

This operator will increment q by one.

Return

a reference to q after the increment.

Parameters
• q: the rational that will be increased.

template<std::size_t SSize>
rational<SSize> mppp::operator++(rational<SSize> &q, int)

Suffix increment for rational.

This operator will increment q by one and return a copy of q as it was before the increment.

Return

a copy of q before the increment.

Parameters
• q: the rational that will be increased.

template<std::size_t SSize>
rational<SSize> mppp::operator-(const rational<SSize> &q)

Negated copy.

Return

a negated copy of q.

Parameters
• q: the rational that will be negated.

template<typename T, typename U>requires RationalOpTypes<T, U> auto mppp::operator-(const T & op1, const U & op2)

Binary subtraction operator.

The return type is determined as follows:

• if the non-rational argument is a floating-point type F, then the type of the result is F; otherwise,

• the type of the result is a rational.

Return

op1 - op2.

Parameters
• op1: the first operand.

• op2: the second operand.

template<typename T, typename U>requires RationalOpTypes<T, U> T& mppp::operator-=(T & rop, const U & op)

In-place subtraction operator.

Return

a reference to rop.

Parameters
• rop: the minuend.

• op: the subtrahend.

Exceptions
• unspecified: any exception thrown by the assignment of a floating-point value to rop or by the conversion operator of rational.

template<std::size_t SSize>
rational<SSize> &mppp::operator--(rational<SSize> &q)

Prefix decrement for rational.

This operator will decrement q by one.

Return

a reference to q after the decrement.

Parameters
• q: the rational that will be decreased.

template<std::size_t SSize>
rational<SSize> mppp::operator--(rational<SSize> &q, int)

Suffix decrement for rational.

This operator will decrement q by one and return a copy of q as it was before the decrement.

Return

a copy of q before the decrement.

Parameters
• q: the rational that will be decreased.

template<typename T, typename U>requires RationalOpTypes<T, U> auto mppp::operator*(const T & op1, const U & op2)

Binary multiplication operator.

The return type is determined as follows:

• if the non-rational argument is a floating-point type F, then the type of the result is F; otherwise,

• the type of the result is a rational.

Return

op1 * op2.

Parameters
• op1: the first factor.

• op2: the second factor.

template<typename T, typename U>requires RationalOpTypes<T, U> T& mppp::operator*=(T & rop, const U & op)

In-place multiplication operator.

Return

a reference to rop.

Parameters
• rop: the multiplicand.

• op: the multiplicator.

Exceptions
• unspecified: any exception thrown by the assignment of a floating-point value to rop or by the conversion operator of rational.

template<typename T, typename U>requires RationalOpTypes<T, U> auto mppp::operator/(const T & op1, const U & op2)

Binary division operator.

The return type is determined as follows:

• if the non-rational argument is a floating-point type F, then the type of the result is F; otherwise,

• the type of the result is a rational.

Return

op1 / op2.

Parameters
• op1: the dividend.

• op2: the divisor.

Exceptions
• zero_division_error: if the division does not involve floating-point types and op2 is zero.

template<typename T, typename U>requires RationalOpTypes<T, U> T& mppp::operator/=(T & rop, const U & op)

In-place division operator.

Return

a reference to rop.

Parameters
• rop: the dividend.

• op: the divisor.

Exceptions
• zero_division_error: if op is zero and only integral types are involved in the division.

• unspecified: any exception thrown by the assignment of a floating-point value to rop or by the conversion operator of rational.

template<typename T, typename U>requires RationalOpTypes<T, U> bool mppp::operator==(const T & op1, const U & op2)

Equality operator.

Return

true if op1 == op2, false otherwise.

Parameters
• op1: first argument.

• op2: second argument.

template<typename T, typename U>requires RationalOpTypes<T, U> bool mppp::operator!=(const T & op1, const U & op2)

Inequality operator.

Return

true if op1 != op2, false otherwise.

Parameters
• op1: first argument.

• op2: second argument.

template<typename T, typename U>requires RationalOpTypes<T, U> bool mppp::operator<(const T & op1, const U & op2)

Less-than operator.

Return

true if op1 < op2, false otherwise.

Parameters
• op1: first argument.

• op2: second argument.

template<typename T, typename U>requires RationalOpTypes<T, U> bool mppp::operator<=(const T & op1, const U & op2)

Less-than or equal operator.

Return

true if op1 <= op2, false otherwise.

Parameters
• op1: first argument.

• op2: second argument.

template<typename T, typename U>requires RationalOpTypes<T, U> bool mppp::operator>(const T & op1, const U & op2)

Greater-than operator.

Return

true if op1 > op2, false otherwise.

Parameters
• op1: first argument.

• op2: second argument.

template<typename T, typename U>requires RationalOpTypes<T, U> bool mppp::operator>=(const T & op1, const U & op2)

Greater-than or equal operator.

Return

true if op1 >= op2, false otherwise.

Parameters
• op1: first argument.

• op2: second argument.

## Standard library specialisations¶

template<std::size_t SSize>
class std::hash<mppp::rational<SSize>>

Specialisation of std::hash for mppp::rational.

using argument_type = mppp::rational<SSize>
using result_type = std::size_t

Note

The argument_type and result_type type aliases are defined only until C++14.

std::size_t operator()(const mppp::rational<SSize> &q) const
Parameters

q – the input mppp::rational.

Returns

a hash value for q.