Written by
Niels Moseley
on
on
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.