Using the GNU MPFR library in C++

The following C++ code wraps the MPFR number type in a class and provides support for the most basic arithmetic operations, such as add, subtract, multiply and divide. In addition, std::ostream is supported for easy printing.

The example calculates sqrt(2) by Newton-Raphson iterations.


#include <iostream>
#include <cstdlib>
#include <cstdint>
#include <cstdio>
#include <stdarg.h>
#include <mpfr.h>

class MP
{
public:
    MP(mpfr_prec_t precision = 4096)
    {
        mpfr_init2(m_value, precision);
    };

    virtual ~MP()
    {
        mpfr_clear(m_value);
    }

    MP& operator=(const double val)
    {
        mpfr_set_d(m_value, val, MPFR_RNDN);
        return *this;
    }

    MP& operator=(const MP &valstr)
    {        
        mpfr_set(m_value, valstr.m_value, MPFR_RNDN);
        return *this;
    }

    MP& operator=(const std::string &valstr)
    {
        mpfr_set_str(m_value, valstr.c_str(), 10, MPFR_RNDN);
        return *this;
    }

    MP operator+(const MP &other)
    {
        MP result(m_value->_mpfr_prec);

        mpfr_add(result.m_value, m_value, other.m_value, MPFR_RNDN);
        return result;
    }

    MP& operator+=(const MP &other)
    {
        mpfr_add(m_value, m_value, other.m_value, MPFR_RNDN);
        return *this;
    }

    MP operator-(const MP &other) const
    {
        MP result(m_value->_mpfr_prec);

        mpfr_sub(result.m_value, m_value, other.m_value, MPFR_RNDN);
        return result;
    }

    MP& operator-=(const MP &other)
    {
        mpfr_sub(m_value, m_value, other.m_value, MPFR_RNDN);
        return *this;
    }

    MP operator*(const MP &other) const
    {
        MP result(m_value->_mpfr_prec);

        mpfr_mul(result.m_value, m_value, other.m_value, MPFR_RNDN);
        return result;
    }

    MP operator/(const MP &other) const
    {
        MP result(m_value->_mpfr_prec);

        mpfr_div(result.m_value, m_value, other.m_value, MPFR_RNDN);
        return result;
    }

    bool operator>(const MP &other) const
    {
        return mpfr_cmp(m_value, other.m_value) > 0;
    }

    bool operator<(const MP &other) const
    {
        return mpfr_cmp(m_value, other.m_value) < 0;
    }

    const mpfr_t& get() const noexcept
    {
        return m_value;
    }

    friend MP abs(const MP &v);

protected:
    mpfr_t m_value;
};

MP abs(const MP &v)
{
    MP result(v.m_value->_mpfr_prec);
    mpfr_abs(result.m_value, v.m_value, MPFR_RNDN);
    return result;
}

std::ostream& operator<<(std::ostream &os, const MP &value)
{
    char *buffer;
    mpfr_asprintf(&buffer, "%RE", value.get());
    os << buffer;
    mpfr_free_str(buffer);
    return os;
}

int main(int argc, char *argv[])
{
    MP half(128);
    MP x(128);
    MP y(128);
    MP eps(128);

    eps  = 1.0e-37; // max error
    half = 0.5;     // constant
    y = 2.0;        // determine sqrt of this value
    x = 1.0;        // starting guess

    // Newton iterations, with error limit.
    MP error(128);
    error = abs(x*x - y);
    while(error > eps)
    {
        x = half*(x + y/x);
        error = abs(x*x - y);

        std::cout << "  x=" << x << "  err=" << error << "\n";
    }

    return EXIT_SUCCESS;
}

Output:


  x=1.500000000000000000000000000000000000000E+00  err=2.500000000000000000000000000000000000000E-01
  x=1.416666666666666666666666666666666666671E+00  err=6.944444444444444444444444444444444450975E-03
  x=1.414215686274509803921568627450980392157E+00  err=6.007304882737408688965782391387922183850E-06
  x=1.414213562374689910626295578890134910119E+00  err=4.510950444942772099280764364849785650649E-12
  x=1.414213562373095048801689623502530243615E+00  err=2.543584239585437226878019693234528701636E-24
  x=1.414213562373095048801688724209698078569E+00  err=0.000000000000000000000000000000000000000E+00

The final result for sqrt(2) = 1.414213562373095048801688724209698078569.