Common operators#
After having explained how mp++’s type coercion works, we can now move on to describe how mp++’s classes can be used to perform mathematical computations.
All of mp++’s multiprecision classes support the four basic arithmetic operations (\(+\), \(-\), \(\times\) and \(\div\)) via overloaded binary operators:
auto r1 = int_t{4} + int_t{3};
assert(r1 == 7);
auto r2 = rat_t{4, 3} - rat_t{2, 5};
assert(r2 == rat_t{14, 15});
auto r3 = real128{5} * real128{2};
assert(r3 == 10.);
auto r4 = real{5} / real{2};
assert(r4 == 2.5);
It is of course possible to mix operands of different types, and the type of the result will be determined by the type coercion rules explained earlier:
auto r1 = int_t{4} + 3; // r1 will be of type int_t.
assert(r1 == 7);
auto r2 = -0.75 + rat_t{1, 2}; // r2 will be of type double.
assert(r2 == -.25);
auto r3 = real128{5} * 2; // r3 will be of type real128.
assert(r3 == 10.);
auto r4 = real{5} / int_t{2}; // r4 will be of type real.
assert(r4 == 2.5);
The behaviour of the division operator varies depending on the types involved. If only
integral types are involved, division truncates, and division by zero throws
a zero_division_error
exception:
auto r1 = int_t{5} / 2; // Integral division truncates.
assert(r1 == 2);
int_t{1} / 0; // This will throw a zero_division_error exception.
If floating-point types are involved, division by zero is allowed and results in infinity:
auto r1 = real128{1} / 0; // Floating-point division by zero generates an infinity.
assert(isinf(r1))
Rational division is always exact, unless the divisor is zero:
auto r1 = rat_t{3} / 4;
assert(r1 == rat_t{3, 4});
rat_t{2} / 0; // This will throw a zero_division_error exception.
The in-place versions of the binary operators are available as well. Given a binary operator, its corresponding in-place counterpart behaves as a binary operation followed by assignment:
int_t r1{4};
r1 += 5; // Equivalent to: r1 = r1 + 5
assert(r1 == 9);
rat_t r2{4, 3};
r2 -= 1.5; // Equivalent to: r2 = r2 - 1.5
assert(r2 == rat_t{-1, 6});
real128 r3{5};
r3 *= rat_t{1, 2}; // Equivalent to: r3 = r3 * rat_t{1, 2}
assert(r3 == 2.5);
real r4{42};
r4 /= real128{0}; // Equivalent to: r4 = r4 / real128{0}
assert(isinf(r4));
It is also possible to use fundamental C++ types on the left-hand side of in-place operators:
int n = 5;
n += int_t{5};
assert(n == 10);
n -= rat_t{3, 4}
assert(n == 9);
double x = 1.5;
x *= real128{2};
assert(x == 3.);
x /= real{3};
assert(x == 1.);
The identity, negation, pre/post increment/decrement operators are also supported for all of mp++’s multiprecision classes:
int_t n;
assert(++n == 1);
n++;
assert(n == 2);
assert(--n == 1);
n--;
assert(n == 0);
rat_t q{1, 2};
assert(+q == q);
assert(-q == rat_t{-1, 2});
All of mp++’s multiprecision classes are contextually convertible to bool
, following the usual rule
that nonzero values convert to true
and zero values convert to false
:
int_t n{3};
if (n) {
std::cout << "n is nonzero!\n";
}
rat_t q{0};
if (!q) {
std::cout << "q is zero!\n";
}
real r{1.23};
if (!!r) {
std::cout << "r is nonzero!\n";
}
In addition to the common arithmetic operators, all of mp++’s multiprecision classes support the relational operators \(=\) and \(\neq\). Real-valued types also support the comparison operators \(>\), \(\geq\), \(<\) and \(\leq\). Any combination of multiprecision and numerical C++ types is supported:
assert(int_t{42} == 42);
assert(3 != rat_t{1, 3});
assert(0.9 < int_t{1});
assert(real128{15} <= int_t{15});
assert(real{"inf", 100} > rat_t{123, 456});
assert(int_t{4} >= rat_t{16, 4});
The comparison operators treat NaN values in the standard way: comparing NaN to any other value returns always
false
, apart from the \(\neq\) operator which always returns true
when NaN is involved. For the floating-point multiprecision
classes, custom comparison functions with special NaN handling are also available (e.g., real_lt()
,
real128_equal_to()
, etc.). These functions can be used as replacements for the comparison operators
in facilities of the standard library such as std::sort()
, std::set
, etc.