# Quadruple-precision float tutorial¶

The real128 class is a thin wrapper around the __float128 type available in GCC and (more recently) clang. __float128 is an implementation the quadruple-precision IEEE 754 binary floating-point standard, which provides up to 36 decimal digits of precision.

real128 is available in mp++ if the library is configured with the MPPP_WITH_QUADMATH option enabled (see the installation instructions). Note that mp++ needs access to the quadmath library libquadmath.so, which may be installed in a non-standard location. While GCC is typically able to resolve the correct path automatically, clang might need assistance in order to identify the correct location of this library.

As a thin wrapper, real128 adds a few extra features on top of what __float128 already provides. Specifically, real128:

• can interact with the other mp++ classes,

• can be constructed from string-like objects,

• supports the standard C++ iostream facilities.

Like __float128, real128 is a literal type, and thus it can be used for constexpr compile-time computations. Additionally, real128 implements as constexpr constructs a variety of functions which are not constexpr for __float128.

In addition to the features common to all mp++ classes, the real128 API provides a few additional capabilities:

• construction/conversion from/to __float128:

real128 r{__float128(42)};                // Construction from a __float128.
assert(r == 42);
assert(static_cast<__float128>(r) == 42); // Conversion to __float128.

• direct access to the internal __float128 instance (via the public m_value data member):

real128 r{1};
r.m_value += 1;                 // Modify directly the internal __float128 member.
assert(r == 2);

r.m_value = 0;
assert(::cosq(r.m_value) == 1); // Call a libquadmath function directly on the internal member.

• a variety of mathematical functions wrapping the libquadmath library routines. Note that the real128 function names drop the suffix q appearing in the names of the libquadmath routines, and, as usual in mp++, they are supposed to be found via ADL. Member function overloads for the unary functions are also available:

real128 r{42};

// Trigonometry.
assert(cos(r) == ::cosq(r.m_value));
assert(sin(r) == ::sinq(r.m_value));

// Logarithms and exponentials.
assert(exp(r) == ::expq(r.m_value));
assert(log10(r) == ::log10q(r.m_value));

// Etc.
assert(lgamma(r) == ::lgammaq(r.m_value));
assert(erf(r) == ::erfq(r.m_value));

// Member function overloads.
auto tmp = cos(r);
assert(r.cos() == tmp); // NOTE: r.cos() will set r to its cosine.
tmp = sin(r);
assert(r.sin() == tmp); // NOTE: r.sin() will set r to its sine.

• NaN-friendly hashing and comparison functions, for use in standard algorithms and containers;

• a specialisation of the std::numeric_limits class template;

• a selection of quadruple-precision compile-time mathematical constants.

The real128 reference contains the detailed description of all the features provided by real128.

## User-defined literal¶

New in version 0.19.

A user-defined literal is available to construct mppp::real128 instances. The literal is defined within the inline namespace mppp::literals, and it supports decimal and hexadecimal representations:

using namespace mppp::literals;

auto r1 = 123.456_rq;   // r1 contains the quadruple-precision
// approximation of 123.456 (that is,
// 123.455999999999999999999999999999998).

auto r2 = 4.2e1_rq;     // Scientific notation can be used.

auto r3 = 0x1.12p-1_rq; // Hexadecimal floats are supported too.