MPFR C++

June 27, 2020Project has been moved to GitHub
April 2, 2015New version 3.6.2 has been released – lots of improvements & bug fixes.
July 24, 2015Fixes for MSVC and new GCC.
April 2, 2015New version 3.6.2 has been released – lots of improvements & bug fixes.
August 24, 2014Added copysign and signbit functions.
July 15, 2014Improved support for 64-bit integers.
June 12, 2014Fixed improper std::setprecision(0) handling, warnings.
June 3, 2014Alternative std::numeric_limits specialization (compatible with std).
May 27, 2014Version 3.5.7 is released (PPC64 support, fixes, etc).
February 15, 2014Various small fixes and improvements.
August 19, 2013Added move c-tor / assignment, more RVO optimization, small fixes.
December 4, 2012Added support for IA64 platform.
October 19, 2012Major update. Now MPFR C++/mpreal is a thread-safe, one-header library.
June 22, 2012Bug fixes, code clean-up by Gael Guennebaud.
May 23, 2012Added Mingw64 support and “fuzzy” comparisons.
January 12, 2012Many small bug fixes and improvements.
September 16, 2011Multiprecision Computing Toolbox for MATLAB – added to software list.
September 5, 2011Compiler warning fixes, better compatibility with old MPFR.
August 24, 2011x64 support (VC2010 & GCC), bug fixes, new math functions.
July 27, 2011Fokko Beekhof created Ubuntu package for MPFR C++.
May 12, 2011Improved factorial function fac_ui() and lgamma(), few bugs are fixed.
April 21, 2011New functions: ia, fmax, fmin, conversion constructor from std::string.
April 11, 2011MPFR 3.0.1 compatibility + few bugs are fixed.
March 6, 2011Boost.Math added support for MPFR C++!!
November 8, 2010Fixed bugs in conversion operators reported by Peter van Hoof.
October 5, 2010Tested custom memory allocator of Doug Lea.
Performance improvement is about 40% on LU decomposition from Eigen!
Check this Performance Chart.pdf for details.
July 15, 2010Added support for Eigen C++ template library for linear algebra.
June 15, 2010Added support for the MPFR 3.0.0.
 more history…

Introduction

This is the home page of high-performance C++ interface for MPFR library. MPFR library allows user to conduct floating-point calculations with virtually any (restricted by available memory only) precision with correct rounding. Besides simple arithmetic operations like “+” and “/” the whole set of mathematical functions is supported: sin, sqrt, pow, log, etc.

MPFR defines custom C-language type to represent floating-point number – mpfr_t. Mathematical manipulations with mpfr_t – variables are done through assembler-look-like functions. For instance, to add two numbers x and y with result in z special function mpfr_add(z,x,y,GMP_RNDN) should be called.
To illustrate the situation, let’s consider two versions of the Schwefel function:

// double - version
double schwefel(double x)
{
    return  418.9829-x*sin(sqrt(abs(x)));
}

//MPFR C - version
void mpfr_schwefel(mpfr_t y, mpfr_t x)
{
   mpfr_t t;
   mpfr_init(t);
   mpfr_abs(t,x,GMP_RNDN);
   mpfr_sqrt(t,t,GMP_RNDN);
   mpfr_sin(t,t,GMP_RNDN);
   mpfr_mul(t,t,x,GMP_RNDN);
   mpfr_set_str(y,“418.9829“,10,GMP_RNDN);
   mpfr_sub(y,y,t,GMP_RNDN);
   mpfr_clear(t);
}

Obviously to write mathematical expressions in such cryptic form requires some time, practice and can be error prone for complex formulas. Moreover in order to use MPFR library existing software should be completely rewritten!
C++ wrapper for MPFR aims to alleviate these issues. It introduces new C++ type for high precision floating point numbers – mpreal, which encapsulates low level mpfr_t. All arithmetic and boolean operators (+, -, *, /, >, !=, etc.) are implemented for mpreal numbers through operator overloading technique. Mathematical functions (sqrt, pow, sin, cos, etc.) are supported too. This makes possible to use MPFR calculations in the same simple way as calculations with numbers of built-in types double or float.
MPFR C++ version of the Schwefel function is:

// MPFR C++ - version
mpreal mpfr_schwefel(mpreal& x)
{
    return  "418.9829"-x*sin(sqrt(abs(x)));
}

Features

Main MPFR C++ features are:

  • MPFR C++ is constantly updated and improved to be up to date with the ongoing development of MPFR library. We support latest MPFR 3.1.1 as well as its trunk version from SVN. (Author uses MPFR C++ on a daily basis, which keeps improvements and updates coming)
  • MPFR C++ allows usage of human-friendly notation for mathematical expressions. For example, to write z = x + y instead of mpfr_add(z,x,y,…). All arithmetic and Boolean operators along with standard mathematical functions are supported. Precision and rounding mode can be easily controlled too.
  • MPFR C++ is simple to use – it is one-header library. Just include mpreal.h to you code and use mpreal numbers the same way you usually use double or float ones. Example is included in distribution. MPFR C++ is the only C++ wrapper which natively supports GNU GCC and Microsoft Visual C++.
  • MPFR C++ allows painless porting from built-in types to MPFR with minimal altering of already typed and tested mathematical expressions. In most cases only renaming of types is needed (e.g. double -> mpreal).
  • MPFR C++ provides high performance interface for plain MPFR. Most operations are designed to be inline which means native MPFR function is called directly without C++ overhead. In contrast to other wrappers MPFR C++ doesn’t use advanced C++ features like function objects, virtual functions, etc. because of significant decrease of speed they suffer.
  • MPFR C++ keeps correct accuracy of intermediate calculations during complex expression evaluation in order to obtain precise final result. Other C++ wrappers use different strategies on handling intermediate calculations which could lead to significant accuracy decreasing of final result (see details in Internals section).

License

MPFR C++ is under GNU General Public License (GPL).

Non-free licenses may also be purchased from the author, for users who do not want their programs protected by the GPL.

The non-free licenses are for users that wish to use MPFR C++ in their products but are unwilling to release their software under the GPL (which would require them to release source code and allow free redistribution). Such users can purchase an unlimited-use license from the author. Contact author for more details.

Download

The MPFR C++ is available for download from GitHub repository.

MPFR C++ can be installed from Ubuntu or Debian repositories maintained by Jerome Benoit.

In order to use MPFR C++ – just include mpreal.h to you code and use mpreal numbers as usual floating-point numbers of double or float types. See example in distribution for more information.

MPFR C++ is free for usage in free projects. If you intend to use it in commercial application please contact author for permission.

Please remember that MPFR (>= 2.3.1) and MPIR (>=2.0.0) (or GMP >=4.2.1) are needed for MPFR C++. If target system is Windows then MPIR and MPFR can be compiled using Brian Gladman’s guide or downloaded from here:

Software using MPFR C++

Extension for MATLAB which allows computing with arbitrary precision. It uses classic OOP techniques (like operator overloading) for tight integration with MATLAB language & environment. As a result multiprecision numbers and matrices can be used in-place of built-in double precision ones. This makes possible to run existing MATLAB scripts with any desired precision without modifications to code.

The Boost C++ libraries are a set of free software libraries that extend the functionality of C++.

Let me know about your project so I can add it to the list.

Internals

One of the most important features that make MPFR C++ distinct from the others is treatment of intermediate results during calculation of whole mathematical expression.

C++ decomposes expressions into atomic operations like “+”, “*“ and stores its results in temporary variables for further usage. For example, expression x = a*b+c*d is calculated by C++ as following:

t1 = a*b
t2 = c*d
t3 = t1+t2
x = t3

where t1, t2, t3 are temporary variables, actually hidden from user. In order to get correct final value such intermediate results should be treated carefully with enough precision.

Main MPFR C++ rule for intermediate results is prec(rop) = max(prec(op1),prec(op2)): result of operation is stored with the max of the precisions of operands.

In other words intermediate operations are conducted with the reasonably maximum precision defined by precisions of arguments and doesn’t depend on precision of target variable (in our example – x).

This is the most natural rule dictated by practical applications, such as numerical differentiation, digital filter convolution, etc. where in order to obtain correct and accurate final result intermediate calculations have to be done with high accuracy.

Other libraries calculate intermediate results with the precision of final variable or round them to some not obvious to user precision which is independent from precision of arguments as well as from precision of final variable. This could lead to a significant reduction in the accuracy of the final result.

Acknowledgements

My sincere gratitude goes to the creators of MPFR for making their library available, Brian Gladman for making MPFR and MPIR (GMP) ports for Windows, numerous contributors, testers and those how provide feedback on MPFR C++ usage in their projects.

History

April 11, 2010:

  • MPFR 3.0.1 compatibility check – OK.
  • Fixed few minor bugs.

November 8, 2010:

  • Fixed bugs in conversion operators. Thanks to Peter van Hoof!

October 5, 2010:

  • Added custom memory allocator of Doug Lea. Thanks to Konstantin Holoborodko!

July 15, 2010:

  • Added functions: machine_epsilon(), mpreal_min(), mpreal_max().
  • Added support for Eigen C++ template library by additional header file mpreal_eigen.h. Thanks to Konstantin Holoborodko!

June 15, 2010:

  • Added support for the latest MPFR 3.0.0.
  • Fixed several bugs. Added const_infinity() function. Thanks to Pere Constans!

May 21, 2010:

August 31, 2009:

  • Added support for Linux Intel Compiler. Cause of minor warning removed. Thanks to Heinz van Saanen!

May 11, 2009:

  • MPFR C++ is under LGPL v2.1 now.

March 9, 2009:

  • Added support of the latest MPFR 2.4.1. Now MPFR C++ is the only C++ interface which is up to date with the newest MPFR version.

November 18, 2008:

  • Added specialized std::swap() for mpreal numbers. Now standard generic algorithms will use efficient version of swap. Fixed some bugs. C++ standard conformance is improved. Thanks to Fokko Beekhof!

October 1, 2008:

  • Added operators <<=, >>=. Improved output formatting. Fixed some bugs. Thanks to Helmut Jarausch!

September 30, 2008:

  • Added functions frexp, ldexp, modf. Thanks to Helmut Jarausch!

September 29th, 2008:

  • Fixed incompatibility with GNU C/C++. Updated output operator<< to take care of ostream.precision() setting. Many thanks to Helmut Jarausch!
  • Minor changes to remove warnings in compilation by gcc.
  • Test: gcc 4.2.3 – ok. Thanks to Dmitriy Gubanov!

September 4th, 2008:

  • Add: check for inexact conversion from floating point to mpreal. Thanks to Brian Gladman!

August 15th, 2008:

  • Add: operators for comparison of mpreal with  built-in types.

August 14th, 2008:

  • Add: division operators when first operand is double.

August 11th, 2008:

  • Add: pre-/postfix operators of increment/decrement. Thanks to Brian Gladman!
  • Update: processing of mpz_t and mpq_t types is improved.

August 8th, 2008:

  • Update: more convenient copy – constructor for mpfr_t type.

August 5th, 2008:

  • Update: majority of functions are changed to be inline.
  • Test: gcc 4.2.3 – ok. Thanks to Dmitriy Gubanov!

August 4th, 2008:

  • Test: Visual Studio 2005 – ok.
  • Public release.

July 11th, 2008: Project start.


1 Star2 Stars3 Stars4 Stars5 Stars (14 votes, average: 4.93)
Loading...

355 Comments

  1. Posted August 9, 2008 at 3:12 am | #

    Hi Pavel,

    Thank you for acknowledging my Windows port of MPFR.

    I run all the mpfr C++ wrappers and I tried yours out today.

    The only problem I had is that you don’t overload the pre and post increment operations (++x, –x, x++, x–) for the mpreal type.

    You might be interested in a special feature that I have added to mpfrcpp for ‘floating point to mpreal’ conversions. I have added a global value called ‘doublebits’ that sets the maximum number of bits allowed in a number when a floating point value is converted to an mpreal (doublebits has a default value and can be set like precision)

    In any conversion from floating point to mpreal an exception is raised if the value being converted has more than ‘doublebits’ bits. An exception is hence generated when an inexact ‘double to mpfr’ conversion is attempted.

    For example with doublebits = 20, the value 8.0 will convert but the value 3.1415926 will raise an exception since it has too many bits set and may hence create a low precision value . This makes it much easier to trap values that are not precise enough to be translated from floating point to mpreals.

    I haqve not done a lot with your wrapper yet but it looks easy to use – thank you for your efforts on this.

    best regards,

    Brian Gladman

  2. Posted August 11, 2008 at 6:38 pm | #

    Hello Brian,

    Thank you for testing mpreal and for valuable suggestions!

    Post-/prefix increment/decrement operations are already added.

    I’ll think about how to handle inexact “double to mpreal” attempts of conversion. Now user can use global MPFR’s functions (mpfr_inexflag_p, mpfr_overflow_p, etc.) to check for such abnormal situations. However, mpreal is focusing on processing expressions, not atomic operations (as MPFR doing). Complex expression could include many intermediate conversions from double to mpreal and how to inform user in which one we have a problem? Maybe using global functions (or exceptions) for whole expression is still the best and only one way.

    Thank you!
    Pavel.

  3. Posted December 20, 2008 at 9:32 pm | #

    Hello Mr. Holoborodko,
    my g++ compiler (3.4.4 with cygwin) does not like your mreal.h. Your style to use a static class member as default value for a function argument as in
    mpreal(const mpq_t u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd);
    This causes the message
    error: `default_rnd’ was not declared in this scope.
    It is tempting and logical to use static data members for default initialization of function arguments but I found it always not to work with some compilers. So I eliminated it from the list of my personal idioms. Would be nice to have a gnu-compatible version of your mpreal – files.
    Best wishes
    Ulrich

  4. Posted December 21, 2008 at 6:01 pm | #

    Hello Mr. Mutze,
    Thank you for your feedback!

    MPFR C++ supports native compilers both for Unix (GNU G++) and Windows (Visual Studio).
    Usually I do tests for GNU with g++ 4.1.2 and 4.2.3 using CentOS and Ubuntu. It works fine. Moreover many people are using MPFR C++ with GNU G++ on various platforms successfully.

    I think that cygwin is using too old version of g++ compiler. It should be just updated to fix this problem.

    Anyway I will check this issue. Or even better, other cygwin users would appreciate if you would provide fix for this problem. Personally I am not using cygwin, so contribution of its experienced user is very welcome.

    Thank you!

  5. Simon Mauch
    Posted April 14, 2009 at 8:52 pm | #

    Dear Mr. Holoborodko,
    your wrapper seems to work like a charm together with eigen.

    (See: http://eigen.tuxfamily.org/dox/CustomizingEigen.html#CustomScalarType)

    Thanks,
    Simon

    • Posted April 15, 2009 at 10:11 am | #

      Dear Simon,

      I appreciate your feedback very much!

      Thank you,
      Pavel.

      P.S. It would be fine if I would be just ‘Pavel’ for everyone.

    • JamesHH
      Posted September 18, 2009 at 1:36 pm | #

      Simon,

      What do you mean “seems to work”? Sure, Eigen compiles fine with MPFR C++, but at least for me it crashes when the ~Matrix() destructor is called.

      Pavel, unless you can point me to some working example of Eigen with MPFR C++, then I think it is false advertising to put Eigen in your “Software using MPFR C++”. If it really does work, I would appreciate a pointer to some more information.

      Thanks.

      • Posted July 21, 2010 at 11:22 am | #

        As for July 15, 2010, Eigen developers have fixed these bug.

        • John
          Posted February 26, 2011 at 10:08 am | #

          Pavel: My program is crashing with Eigen matrices if I set the precision too high (>30000, e.g., 31000)

          Do you have any idea if this is cause by your custom memory allocator? I saw that the guys at Eigen made available a version of your MPFR wrapper that does not use the custom allocator. I was wondering if there is any easy way in your wrapper to turn off the custom allocation instead of replacing the whole wrapper from the Eigen website

          Could you confirm??

          • Posted February 27, 2011 at 12:10 pm | #

            I am sure the problem is not in allocator – it is being used in several Linux distros as core allocator.

            JamesHH, Cannelle Bertrand reported similar problems related with memory allocation for custom scalar types in Eigen – one was fixed, another (with sparse matrices) left without attention from Eigen developers.

            But none of them were related to MPFR C++ itself.
            Eigen comes with old version of MPFR C++ – eigen guys promised to give me access to Eigen source base so I can update MPFR C++ part, but I didn’t get one.

            This page provides the latest updates. Please comment out 493 line in mpreal.cpp to disable custom allocator for your tests.

            I’ll add compile-time flag to enable/disable custom allocation in the next update for convenience.

            Please notify me about results of your tests.

            Update: Matrices with 31000 bits precision numers might require huge memory. Is it possible that it is just not enough free heap memory?

  6. Abel Rodríguez
    Posted April 18, 2009 at 11:52 am | #

    Hi Pavel.
    I must say your wrapper is fantastic. I really don’t imagine myself changing all my code to those criptic MPFR functions.

    However, I must ask you something too:
    When I use some mpfr function, using your wrapper, the result always has the same precision as the argument supplied to the function, if the argument is a mpreal. I know this is a MPFR behavior, and in MPFR you can change this. In your wrapper, there is a way to select the precision of the result, without regard the precision of the argument? I haven’t find one yet. By the way, I tried to use mpreal::set_default_prec(), but the behavior remains.

    I’d really appreciate your answer.
    See you later!

    • Posted April 20, 2009 at 12:41 pm | #

      Hi Abel.

      Thank you for the good words!

      You are right, in MPFR C++ precision of the result depends on the precision of function argument(s).

      That’s because how C++ decomposes expressions into simple operations. For example, complex expression like y=(1+cos(x))/(1+sin(x)) C++ evaluates in several steps using temporal variables:
      t1 = sin(x)
      t2 = 1+t1
      t3 = cos(x)
      t4=1+t3
      t5 = t4/t2
      y = t5

      On every step appropriate overloaded arithmetic operator is called. During these temporal evaluations we don’t know the precision of final variable – y. All we have is arguments.

      Maybe it is the most natural choice to conduct operations with the information we only have – based on precision of arguments. Up to now MPFR C++ follows this strategy.

      Generally speaking, by using any C++ interface to simplify usage of native MPFR user sacrifices flexibility of scrupulous precision control for every operation in the expression and have to rely on choices made in particular C++ wrapper.

      MPFR C++ strategy works the best for the case when all variables (target, arguments) have the same precision, or target variable has lower precision than arguments. This is particularly useful for the applications where in order to obtain correct and accurate final result (even in low precision) intermediate calculations have to be done with high accuracy/precision. Examples are: numerical differentiation and digital filter convolution.

      So the simplest workaround for your case is to use the same precision for all variables.

      Another way is to redesign MPFR C++ interface so that all intermediate operations will be done with the precision adaptively selected based on precision of arguments and target variable. I’m planning on adding such feature in the future releases.

  7. Guido W. Pettinari
    Posted May 6, 2009 at 10:29 pm | #

    Hi Pavel!

    Thank you for your wrapper, I find it extremely useful and intuitive.

    Nevertheless, I have a problem. By running my code using the mpreal class and setting the precision to 64 bits via mpfr::mpreal::set_default_prec ( 64 ), I obtain different results from when I run it with standard C++ double precision (still 64 bits).

    Is there an obvious reason for this behaviour, other than a possible mistake of mine?

    Thank you for your attention,

    Guido

    P.S. The mpreal objects I use are created after calling mpfr::mpreal::set_default_prec ( 64 ).

    • Posted May 7, 2009 at 3:20 pm | #

      Hi Guido!

      Thank you for using MPFR C++!

      There is no mistake in your code nor in MPFR C++.

      Native MPFR uses different technique for floating number representation than double of IEEE-754 standard.

      That is why MPFR cannot emulate standard double arithmetic by simply setting precision to 53 bits (mantissa of double occupies 53 bits, not 64 as you used).

      Special not-obvious tricks are needed to do this: subnormalizing after each operation, etc. More detailed information you can find in MPFR manual (see pages 33-34): http://www.mpfr.org/mpfr-current/mpfr.pdf

      Emulation of double arithmetic is not the goal of MPFR and these tricks require working with MPFR on low level, not through C++ wrapper.

  8. Guido W. Pettinari
    Posted May 8, 2009 at 7:10 pm | #

    Hi Pavel,

    thank you very much for your prompt answer! I now understand why the results were different.

    I would be grateful if you could answer another question: do you know if there is any arbitrary precision C++ wrapper/library that computes Sine and Cosine integrals – Si(x) & Ci(x) – efficiently, as defined in here http://en.wikipedia.org/wiki/Trigonometric_integral? I was thinking to just take GNU GSL source code for such functions and replace “double” with “mpreal”, but I guess it is not the best way to proceed. Another way could be to start from the Exponential Integral Ei(x) – which is included in MPFR – to obtain Si(x) and Ci(x) but the are complex numbers involved and I do not want to mess with them.

    Thank you again,

    Guido

    • Posted May 11, 2009 at 11:22 am | #

      Hi,

      I don’t know any particular C++ multi-precision library which supports Si(x) and Ci(x).
      Probably the best way is to write your own functions based on MPFR C++. As far as I see it is not very difficult. I would gladly add these functions to MPFR C++ if you will decide to share your source code then.

      FYI GSL is already ported to native (not C++) MPFR: http://marcomaggi.github.com/docs/mpgsl.html
      Maybe it supports what you are looking for.

      Best regards,
      Pavel.

  9. Guido W. Pettinari
    Posted May 18, 2009 at 5:39 am | #

    Thank you for your answer.

    Alas the MPFR port of GSL does not include the functions I am looking for. In the end I solved my problem in another way. I had to compute the difference between the cosine integral and sinc for very large arguments, and I needed high precision since Ci(x) ~ Sinc(x) when x is large.

    However I found out that I could use series expansion. In fact it turned out that

    CosIntegral[x] – Sinc[x] ~ (6/x^4 – 1/x^2) Cos[x] + (24/x^5 – 2/x^3 ) Sin[x].

    Thank you anyway for the support!

    Cheers,

    Guido

  10. Daniel B.
    Posted August 19, 2009 at 11:52 pm | #

    Dear Pavel,

    thank you for writing this great wrapper and putting up the link to already compiled GMP and MPFR.

    I would like to ask you one thing. I tried the exaple code, that comes with your wrapper and as soon as I move any variable out of the main(), I get an assertion error in ini2.c (about precision I guess).

    So this code …

    mpreal x = "420.968746359948568";
    	
    int main(int argc, char* argv[]){
    	mpreal::set_default_prec(128);
    	...
    

    generates the error, while this

    int main(int argc, char* argv[]){
    	mpreal x = "420.968746359948568";
    	mpreal::set_default_prec(128);
    	...
    

    does not generate the error, even though in the second case the precision is set only after the init of X, which I though was be the problem in the first example. So, to sum it up, is there any way I can use global variables of mpreal type in my applications?

    Thank you for a response in advance!
    Daniel.

    • Posted August 20, 2009 at 10:18 pm | #

      Hi Daniel!

      Thank you for your comment!!

      Current design of MPFR C++ doesn’t allow ‘mpreal’ number to be used as global variable. Generally, global variables are considered as bad solution in C++.

      If you want them anyway you can to get around this restriction by using local static variables in global functions.

      For details, please check Item 47 in Scott Meyers. Effective C++: 50 Specific Ways to Improve Your Programs and Design (2nd Edition) .

      Cheers,
      Pavel.

      • Daniel B.
        Posted August 21, 2009 at 12:11 am | #

        Thank you for an answer, I know what statics are, but I will look into the book anyway:)

      • Daniel B.
        Posted August 21, 2009 at 4:47 am | #

        Hello Pavel,
        me again. After trying to get the code rid of global variables, I stumbled upon a problem with linking static variables. The following code

        #include "mpreal.h"
        
        using namespace mpfr;
        using namespace std;
        
        class X {
        public:
        	static mpreal x;
        	};
        
        int main(int argc, char* argv[]){
        	X::x = "420.968746359948568"; 
        	return 0;
        	};
        

        gives me a linker error telling me ‘error LNK2001: unresolved external symbol “public: static class mpfr::mpreal X::x” ‘. Can this be solved? And if so, could you please direct me to the topic or keyword, is used to solve this problem?

        Thank you once again in advance,
        Daniel B.

  11. Daniel B.
    Posted August 31, 2009 at 8:55 pm | #

    Dear Pavel,

    thank you very much!

    All the best,
    Daniel.

  12. Posted December 15, 2009 at 11:38 am | #

    Hello, thanks for your nice software!

    I’d like to use it for MPACK (MBLAS/MLAPACK).
    http://mplapack.sourceforge.net/
    How about wrapping MPC as well?

    I prepared general (not very well one) for GMP.
    http://mplapack.cvs.sourceforge.net/viewvc/*checkout*/mplapack/mpack/include/mpc_class.h?revision=1.5

    any comment is really appreciated.

    Thanks!

    • Posted December 23, 2009 at 2:00 pm | #

      Hi Maho!

      Thank you for your comment!
      I really like your ideas of MPACK and high precision optimization solvers.
      I’ve checked your web site and I think you are doing very impressive stuff.

      MPFR library offers very nice features over GMP, like correct rounding, high level functions, etc. I think it would suit MPACK needs much better than bare GMP.

      Besides there are some problems with GMP usage on Windows platform: http://www.gladman.me.uk/. So, if you want MPACK to be used on Windows it is better to consider MPIR: http://www.mpir.org/. MPFR can use it instead of GMP.

      C++ interface for GMP is already exist and distributed along with GMP source code (gmpxx.h). I didn’t check it personally, but maybe it worth considering before developing new one.

      I have plans to make C++ interface for MPC but I cannot promise exact dates, sorry.

      I would be honored if you would use my library MPFR C++ for MPACK. I am open for any questions and ready to provide you assistance on that matter.

      Thank you!

  13. Nakata Maho
    Posted December 23, 2009 at 4:18 pm | #

    Hi Pavel, thanks for your comment!

    I have already been using GMP via gmpxx.h. Above mentioned complex C++ wrapper is
    based on GMP. Problem here is not so many functions, as you suggest.
    Thanks for MPIR. I didn’t know about it. MPACK infrastructure is designed to be easy to
    port to a multiple precision library. What I need are four types; “REAL”, “COMPLEX”, “INTEGER” and “LOGICAL”. If someone make a wrapper to MPFR, I can port to MPFR immediately.
    I’d like to use MPFR for better calculation evaluation.

    Anyway please take your time. Hope I can do some contribution to you.

    Best regards,
    Nakata Maho

  14. Jerry Gagelman
    Posted February 8, 2010 at 7:50 pm | #

    First I’d like to thank Pavel for the valuable wrapper he has written. It has saved many people lots of work! I’d also like to call everyone’s attention to another “templated” linear algebra library that I have been using with the mpreal type and with which I have been happy — with both MPFRC++ and the library:

    http://math.nist.gov/tnt/index.html

    It’s like a lighter weight version of Eigen, one more devoted to core linear algebra. Everything is defined in header files (hence no libraries to build) and it uses doxygen documentation. Note: I am using version 3.0.12 from the download page.

    Jerry

  15. Jogi
    Posted April 12, 2010 at 6:52 pm | #

    Hi Pavel,
    Really nice piece of work.

    I have a couple of questions upon usage howerver. I am trying to assign a double value to an mp real and I get an exception.

    mpreal::set_default_prec(128);
    mpreal::set_double_bits(32); // I am assuming this is decimal places — please advice

    mpreal d = 2.11 ;

    terminate called after throwing an instance of ‘mpfr::conversion_overflow’

    Is this correct? I would assume that I could assign a double to an mpreal.

    • Posted April 15, 2010 at 10:04 pm | #

      Hi!

      To convert double values to mpreal you can use two ways:

      1. mpreal d = 2.11;
      2. mpreal d = “2.11”; // preferable, since there is no conversion to double

      Second way is preferable, since there is no transitive conversion to double. Also numbers way beyond double precision can be assigned, like

      mpreal d = “2.1234567891234567891234567”;

      Generally you do not need to invoke mpreal::set_double_bits(). It is needed only for specific purposes (read first comment for more information).

      Thanks.

  16. Bassam Shehadeh
    Posted August 26, 2010 at 3:03 pm | #

    Hello

    I’m trying to use mfprc++ to build a high precision code do a massive computation. I settled everything had the mpfrc++ test work successfully. When try to compile my code I bumbed into this error:
    error: conversion from mpfr::mpreal to int is ambiguous

    this happen because I’m trying to promote an integer to mpreal. Is there any function does this promotion? I’ll be very thankful for any help

    Thank you!
    Bassam

    • Posted August 27, 2010 at 11:17 am | #

      Hello

      I’ve added type conversion operator for mpreal to int transformation. Please download new version and try it – check if it solves your problem.
      Something like this should work fine

      mpreal x = "1.5";
      int y = x;
      
      • Bassam Shehadeh
        Posted August 27, 2010 at 3:07 pm | #

        Pavel

        Yes, it did work. Now the compiler (gcc) is accepting converting mpreal to int.

        The package is very nice

        Many thanks

        • Pau
          Posted July 12, 2012 at 5:42 pm | #

          Pavel,

          oddly enough, current version of MPFRC++ (july 12, 2012) seems to lack mpreal to int conversion.
          This simple code

          mpreal x = "420.968746359948568";
          int i = x;

          fails to compile (gcc 4.4.3) with error

          error: cannot convert ‘mpfr::mpreal’ to ‘int’ in initialization

          Did you drop this feature at some point?

          Best,
          /P

          • Posted July 12, 2012 at 5:55 pm | #

            Hi Pau,

            Yes you are right, I’ve dropped all implicit conversion operators from mprel to standard types. Since in some situations compiler does silent conversion of mpreal to double or int and calls non-multiprecision functions from std namespace.

            For example this happens if user calls std::sqrt() with mpreal as a parameter. Now at least compiler warns user with an error.

            There are explicit operators instead:

            toDouble()
            toLong();
            toULong();

  17. Sandeep Menon
    Posted September 18, 2010 at 2:39 am | #

    I’m aware that libmpfr is thread-safe, but does this extend to mpfrc++ ?

    • Posted September 18, 2010 at 8:46 pm | #

      Current version of MPFRC++ is not thread-safe since it has several static members global for all instances (in all threads), related to default precision and rounding mode. Access to these members is not protected by mutexes.

      Apart from that, if you setup default precision and rounding mode only once in one (main) thread, than I believe MPFRC++ can be used in multithreading computations safely.

      Anyway we are planning to implement this feature in the next release.

  18. Posted September 30, 2010 at 1:27 am | #

    Thank you for your code. My wife use it for high precision calculation of matrix minors.

    All is good except the function mpreal::to_string(). It does not take into account decimal separator of output stream, and returns something like «1.2345e-1» instead of «0.12345» (which is shorter).

    Also we have debugging problems since MPFR C++ numbers are not easily viewable in the debugger.

    How about small support for C++0x: adding move constructors and move assignment operators?

    • Posted September 30, 2010 at 10:36 am | #

      Thank you for your feedback.

      mpreal::to_string() converts number in commonly used scientific notation.
      If you want precise output format manipulation you can use formatted output functions (section 5.9 in MPFR manual).

      You can use them directly with mpreal numbers since there is a type conversion operator from mpreal to mpfr_t.

      So something like this should work fine (although I am not sure about Windows & Visual C++):

      mpreal x = "0.01234567789";
      mpfr_printf("%25.15Rg", x); // call low-level MPFR function

      I’ll improve this part of MPFR C++ in the upcoming versions.

      As for C++0x features – I’ll include them as soon as they will be widely supported.
      I think it will be much more important to implement C++0x TR1 mathematical library based on mpreal.

      What do you think?

      I would appreciate any other ideas on further improvement as well as more information on how MPFR C++ has being used in your (or your wife’s) research.

  19. Peter van Hoof
    Posted November 7, 2010 at 4:27 am | #

    I have been using your code to evaluate some series expansions that suffer from serious cancellation errors. When I did this, I ran into several problems.

    1) I got various compiler errors due to ambiguous overloads of pow() and sqrt(). In my opinion you should remove math functions from your header file that don’t have at least one mpreal as an argument as they are all prone to this problem. This snippet shows the problem:


    #include
    #include "mpreal.h"

    using namespace mpfr;

    double sub1(double x, double y)
    {
    return pow(x,y);
    }

    double sub2(double x)
    {
    return sqrt(x);
    }

    void sub3(mpreal x)
    {
    // do somthing with mpreals...
    }

    2) The routine for casting an mpreal to int seems to be missing. I.e. the following code doesn’t work:


    mpreal x;
    int i = static_cast(x);

    3) This problem was the hardest to track down. The routines for casting mpreal to any integral type work incorrectly. They should always truncate the number, i.e. always round towards zero, independent of the current setting of the FP rounding mode. The following code snippet illustrates this and fails on my system.


    #include
    #include "mpreal.h"

    using namespace mpfr;

    int main()
    {
    double x = 2.6;
    long i = static_cast(x);
    mpreal y = 2.6;
    long j = static_cast(y);
    assert( i == j );
    return 0;
    }

    Changing the routines to something like


    inline mpreal::operator unsigned long() const
    {
    return mpfr_get_ui(mp,GMP_RNDZ);
    }

    and similar for the other three conversion routines should solve the problem.

    Otherwise it was great working with your code, so thanks for the effort!

    • Posted November 8, 2010 at 3:47 pm | #

      Hi,

      Thank you very much for the bug report and suggestion.

      1. I’ve added mpreal->int conversion operator.
      2. Fixed bug in conversion to integer types.

      But I keep pow, sqrt functions which accept built-in types and return mpreal numbers. I did that on purpose to avoid incorrect evaluation of mixed expressions (which most likely to appear when switching from built-in types to mpreal):

      mpreal x,y,z;
      x = y*pow(0.5,10.5);
      

      In this case programmer expects that pow will be evaluated using multiprecision arithmetic. That is why I included functions which looks like from C++ standard library but actually they do all the calculations using high-precision MPFR.

      Otherwise pow(0.5,10.5) would be evaluated in double precision and then converted to mpreal silently! This would corrupt final precision of the result.

      Moreover, such functions are restricted only to mpfr namespace, and it is possible to mix them with standard library functions. For your example:

      using namespace mpfr;
      using namespace std;
      
      double sub1(double x, double y)
      {
      	return ::pow(x,y); // or std::pow(x,y) = use pow() from std 
      }
      
      double sub2(double x)
      {
      	return ::sqrt(x); // or std::sqrt(x) = use sqrt() from std
      }
      
      mpreal sub3(mpreal x)
      {
      	return sqrt(x);  // or mpfr::sqrt(x) = use sqrt from mpfr
      }
      

      This way programmer should decide explicitly what to use – there is no hidden conversions to double, etc.

      Besides, standard C++ math-functions cannot provide precise result for some values even of built-in types. MPFR has very nice replacements for them, which are optimized for built-in types, and can provide high accuracy using multi-precision arithmetic.
      For instance, mpfr_ui_pow_ui.

      New version is on the site already – please check it.
      Hope this helps.

      • Peter van Hoof
        Posted November 9, 2010 at 1:43 am | #

        When viewing this:

        mpreal x,y,z;
        x = y*pow(0.5,10.5);
        

        I would like to remark the following. You will always have to be careful when mixing double (constants) and mpreals. By the same token, people may expect the following to work as well:

        mpreal x,y,pi;
        x = 2./3.; // may or may not give full precision, but likely not
        x = 2.*pow(0.5,10.5)/3.; // same as before, but less obvious
        x = pow(0.4,10.1); // again, not full precision
        pi = 2.*asin(1.); // only double precision result...
        

        In all examples the user may expect full precision, but will most likely not get it. In the first two examples it is implementation defined whether 2./3. is evaluated in double precision and then converted to mpreal, or the other way around (but for optimization reasons it will likely be the former). In the third example the problem is even more subtle and very hard to detect. Neither 0.1 nor 10.1 can be represented exactly in binary notation, so the posted code will not give the same precision as

        x = pow(mpreal("0.4"),mpreal("10.1")); 
        

        since in the latter the binary representations of 0.4 and 10.1 will have all bits correct (within rounding precision), while in the former that will not be the case (they will be correct only to double precision and then padded with 0 bits). The fourth example should be obvious, here the double version of asin will always be taken since there is no other. The basic problem is that when automatic conversions to and from mpreal are defined, it becomes hard to predict what the compiler will do (and to some extent even impossible). So my advice would be to never mix double constants (or variables) and mpreals in the same statement to assure maximum precision. The overloaded versions of sqrt and pow that do not take mpreals as an argument may create a false sense of security. And if you follow my advice, you will never need them anyway…

        Luckily C++0x will allow us to alleviate this problem somewhat by allowing us to define true mpreal constants and do away with the cumbersome notation mpreal(“10.1”)…

        • Posted November 9, 2010 at 10:00 am | #

          Sorry for making unclear statement in my comment.

          @”So my advice would be to never mix double constants (or variables) and mpreals in the same statement to assure maximum precision. ”

          Exactly. This is the philosophy of MPFR C++. The overloaded versions of sqrt and pow exist solely for that purpose – they push compiler to generate error when user try to mix mpreal and double in the same expression or scope (as you experienced at the first place).

          So that programmer can pay attention to that issue (which is not obvious as you said) and decide explicitly (by using string literals or namespace resolution std::) what to use and be more careful in general.

          Of cause, user should use string literals to present mpreal constants. But this is not obvious for beginners and MPFR C++ tries to draw attention of a user by declaring functions conflicting with standard-math library, so compiler screams on mixing. So user can investigate further.

          Especially it is important when porting algorithms from built-in types.

          To sum up, proper usage of MPFR C++ includes:

          1. Constants should be presented by string literals, like “10.1”.
          2. No mixing with std math functions is allowed in the same expression or scope.

          By overloading of std functions MPFR C++ tries to solve 2nd issue – compiler gives error on mixing. But I don’t know how to solve 1st in the same time, since it contradicts to solution of 2nd. Do you have better idea how to solve both of them simultaneously?

  20. Peter van Hoof
    Posted November 7, 2010 at 6:15 am | #

    The blog software ate all my text between angled brackets, despite it being protected as “code”! Anyway, the missing parts are as follows: the #includes should include cmath and cassert, resp., while the static_cast statements should cast to int, long, long, resp.

  21. Anonymous
    Posted November 18, 2010 at 3:43 pm | #

    Hello
    I have tried to use MPFR C++ with Aigen but I have an error that I
    cannot understand. I don’t know whether the problem comes from Eigen or from
    MPFR C++.

    My code runs correctly when the numerical type of the matrix is double but does
    not work when the type is mpreal in Sparse Module.
    Can you give me some hint about this error ?

    Thank you for your answer.

    Bertrand

    To reproduce my bug, you can use this code

    ……

    • Posted November 18, 2010 at 4:42 pm | #

      Could you send me your cpp files by e-mail: pavel@holoborodko.com
      Website engine has damaged you code.

      Also please describe what error you have, compiler, MPFR version, etc.

  22. Igor Krivenko
    Posted November 26, 2010 at 3:52 am | #

    Hello Pavel,

    thank you very much for a convenient C++ wrapper. The most appreciated part of your work for me is the integration between the Eigen matrix library and the MPFR arithmetic (currently I’m working on an algorithm dealing with matrices which are numerically very close to singular).

    So, my question is about mpreal_eigen.h. As far as I can see, it explicitly instantiate a number of functions (for example, template mpfr::mpreal machine_epsilon()). Every translation unit of my program, which includes the file, receives a copy of that code. And a linker is not happy at all to see the duplicated symbols, when it tries to link the object files together (I use gcc 4.4.4 on Linux).
    Could you suggest a solution/workaround for the problem?

    • Posted November 26, 2010 at 1:34 pm | #

      Hello Igor,

      It is strange problem since mpreal_eigen.h is idempotent header with protection against duplication:

      #ifndef MPREALSUPPORT_H
      #define MPREALSUPPORT_H
      ......
      #endif // MPREALSUPPORT_H
      

      Have you by any chance removed these header guards? Or already defined MPREALSUPPORT_H somewhere else?

      • Igor Krivenko
        Posted November 26, 2010 at 10:05 pm | #

        I have neither removed nor changed the guards. In fact this problem is not about double inclusion, but about duplicated symbols in object files. To clarify the situation I describe the steps to reproduce the error.

        I have directory mpreal which contains all files of MPFR C++, including mpreal.o, dlmalloc.o and mpreal_eigen.h.

        Beginning of mpreal_eigen.h:

        #ifndef MPREALSUPPORT_H
        #define MPREALSUPPORT_H

        #include "mpreal.h"
        #include
        #include

        Then I have 2 source files of my program, for example a.cpp and b.cpp

        a.cpp:

        #include"mpreal/mpreal.h"
        #include"mpreal/mpreal_eigen.h"

        int main()
        {
        return 0;
        }

        b.cpp:

        #include"mpreal/mpreal.h"
        #include"mpreal/mpreal_eigen.h"

        int f()
        {
        return 0;
        }

        Each of them compiles normally:

        $g++ -c a.cpp -I/usr/include/eigen2/
        $g++ -c b.cpp -I/usr/include/eigen2/
        $

        But a linker complains about multiple definitions when I try to link the object files together:

        $g++ a.o b.o mpreal/dlmalloc.o mpreal/mpreal.o -lmpfr
        b.o: In function `Eigen::NumTraits::Real Eigen::machine_epsilon()':
        b.cpp:(.text+0x0): multiple definition of `Eigen::NumTraits::Real Eigen::machine_epsilon()'
        a.o:a.cpp:(.text+0x0): first defined here
        b.o: In function `Eigen::NumTraits::Real Eigen::precision()':
        b.cpp:(.text+0x28): multiple definition of `Eigen::NumTraits::Real Eigen::precision()'
        a.o:a.cpp:(.text+0x28): first defined here
        b.o: In function `mpfr::mpreal Eigen::ei_random()':
        b.cpp:(.text+0x4c): multiple definition of `mpfr::mpreal Eigen::ei_random()'
        a.o:a.cpp:(.text+0x4c): first defined here
        b.o: In function `mpfr::mpreal Eigen::ei_random(mpfr::mpreal, mpfr::mpreal)':
        b.cpp:(.text+0xb0): multiple definition of `mpfr::mpreal Eigen::ei_random(mpfr::mpreal, mpfr::mpreal)'
        a.o:a.cpp:(.text+0xb0): first defined here
        b.o: In function `mpfr::ei_isMuchSmallerThan(mpfr::mpreal const&, mpfr::mpreal const&, mpfr::mpreal const&)':
        b.cpp:(.text+0x19e): multiple definition of `mpfr::ei_isMuchSmallerThan(mpfr::mpreal const&, mpfr::mpreal const&, mpfr::mpreal const&)'
        a.o:a.cpp:(.text+0x19e): first defined here
        collect2: ld returned 1 exit status
        $

        • Posted November 26, 2010 at 11:39 pm | #

          Generally template specification in header file+its multiple inclusion should be treated by compiler well – it should resolve duplicates automatically (which is not the case with usual functions).
          I don’t have much experience with g++ but here is some info relevant to the problem:
          http://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html

          Another way is to add inline before all function definitions in in mpreal_eigen.h which causes the error.

          I hope someone who reads our comments and has experience with g++ can help to solve the issue.

          • Igor Krivenko
            Posted November 27, 2010 at 1:09 am | #

            Thank you very much for the link and the advice about inline keyword! Inlining eliminates the issue. Moreover, I took a look at Eigen’s sources (Eigen 2) and found out that the corresponding functions for standard numerical types are declared as inline. So I think it would be correct to follow this rule in your header file too.

          • Posted November 27, 2010 at 11:19 am | #

            Yes, you are right.
            I’ve included this fix in mpreah_eigen.h

          • John
            Posted February 11, 2011 at 6:45 am | #

            Sorry to spoil the party, but including the inline keyword makes both MS’s C++ compiler (VC++ 2008) and Intel’s C++ compiler (11.1) to fail compilation. Both were running under Windows 7 Pro x64. However, the fact that the inline keyword caused syntax errors, makes me doubt that the architecture is a factor.

            For more details, see my posts below (which at the moment are pending moderation)

  23. Anonymous
    Posted November 28, 2010 at 7:08 pm | #

    Hello Pavel,

    I’m a noob programmer. I’m trying to compile your example (in Windows) in CodeBlocks using GNU GCC Compiler.
    I dont undestand the error that takes: undefined reference to ‘mpfr_init2’
    that is inside mpreal::mpreal() in mpreal.cpp

    I have tried Cygwin GCC and takes the same error.

    I have all the files of mpfr and mpir in the same directory within the files of mpreal and included all the libs to the proyect.

    • Posted November 29, 2010 at 11:56 am | #

      Hello,

      It is hard to guess but it seems that MPFR’s binary library is not properly supplied to the linker.

      Here is correct instruction from makefile to generate example.cpp

      mpreal.o: mpreal.cpp mpreal.h
      	g++ -c mpreal.cpp
      
      example.o: example.cpp mpreal.h
      	g++ -c example.cpp
      
      dlmalloc.o: dlmalloc.c dlmalloc.h
      	g++ -c dlmalloc.c
      
      example: example.o mpreal.o dlmalloc.o
      g++ example.o mpreal.o dlmalloc.o $(LDIR)libmpfr.a $(LDIR)libgmp.a -o example
      

      Where LDIR is the path to the MPFR & GMP binaries.

      • Posted September 2, 2013 at 7:03 am | #

        Hi Pavel,

        I just run into the same situation as Anonymous. I use CodeBlocks and I’m also a newbie in C++ (just switching from Ruby for this single project).
        I use CodeBlocks built-in features to build and run the program. I have first tried to write the program using the GMP library and compiling/linking went well, then I switched to MPFR, and there was no problem neither. However GMP and MPFR libraries were installed by package manager.
        Now I have manually downloaded your mpreal.h, and placed it just where gmp.h, gmpxx.h and mpfr.h reside.

        I’m using include <mpreal.h> in the source, but when I set the linker the extra argument: '-lmpreal' it throws an error.
        Is it possible that even though the header file is called ‘mpreal.h’ I have to set the linker to use ‘-lmpfr’? This way your example.cpp compiles without error.
        Sorry for the n00b question, I’m used to scripted languages, and c++ feels like deep water even just setting up proper compiling/linking.

  24. Anonymous
    Posted November 29, 2010 at 4:49 pm | #

    Thanks.

    But it gives another error:
    ||Warning: .drectve `/DEFAULTLIB:”LIBCMT” /DEFAULTLIB:”OLDNAMES” ‘ unrecognized|
    and
    mpfrc++\mpfr.lib(.\Win32\Release\round_prec.obj)|| undefined reference to `_alloca_probe_16’|

    • Posted November 29, 2010 at 4:59 pm | #

      It looks like you are trying to link MPFR binaries generated by Visual C++ which is incompatible with GCC.

      You should compile MPFR, MPIR/GMP by gcc to use them in gcc-based project.

  25. Anonymous
    Posted November 29, 2010 at 6:31 pm | #

    As I said the compiler that I am using is GNU GCC Compiler.
    I dont know what Im doing wrong.
    I have tried with the other option ‘win32_gmp_mpfr.zip’ and it gives the same errors.

    • Posted November 29, 2010 at 7:42 pm | #

      win32_gmp/mpir_mpfr.zip were compiled by Visual C++.

      Hence their format is not compatible with GCC you are using in your project.

      Thus you should compile MPIR/MPFR by GCC in order to use them in your project.

  26. Anonymous
    Posted December 1, 2010 at 7:09 am | #

    Hi Pavel,

    Ok, it works.
    The problem I had was that I linked the libraries in CodeBlocks in a not properly order (it seems that is necesary include first ‘libmpfr.a’, second ‘libgmpxx.a’ and finally ‘libgmp.a’).
    (Ok, I didnt want use the ‘make’ file).

    • Posted December 1, 2010 at 9:06 am | #

      Although problem is very strange – I am glad you find the solution. And thank you for reporting it.

  27. Jerry Gagelman
    Posted January 15, 2011 at 12:46 am | #

    A lot of recent discussion on this “board” concerns build issues with different compilers and platforms. Admittedly the makefile included in the mpfrc++ source tree is only the most basic, the only targets, for instance, being static libraries. To address these issues, I have uploaded a “Gnu-ized” version of mpfrc++ to sourceforge.

    With this one can build and install the library with the familiar sequence:

    ./configure && make && sudo make install

    Configuration options (see ./configure --help) provide a systematic way of passing compiler/linker flags and fine-tuning build specifications. In particular, it provides a painless way for building mpreal as a dynamic library on practically any platform.

    The source code is taken from this website and released under the identical license.

    Everything is in the /trunk branch of the repository. The SVN check-out command

    svn co https://mpfrcpp.svn.sourceforge.net/svnroot/mpfrcpp/trunk [your-path]

    will install the entire source tree in your-path.

  28. John
    Posted February 11, 2011 at 6:23 am | #

    Hi,

    I have been using your code and it has been working well so far. Thank you!

    Now, I’m trying to use your code with Eigen 2. I downloaded the header file you recommended “mpreal_eigen.h”. However, the code does NOT compile. There are four errors, all related to invalid storage class for a template declaration (see below). Eigen code alone compiles well, as does your code alone, but that header that integrates your code and Eigen is causing troubles. Any help on that?

    I’m using Intel’s compiler v11.1 x64 in Windows 7 Pro x64.

    Thanks in advance

    John

    1>C:\mpfrc++\mpreal_eigen.h(51): error: invalid storage class for a template declaration
    1> inline template mpfr::mpreal machine_epsilon()
    1> ^
    1>
    1>C:\mpfrc++\mpreal_eigen.h(56): error: invalid storage class for a template declaration
    1> inline template mpfr::mpreal precision()
    1> ^
    1>
    1>C:\mpfrc++\mpreal_eigen.h(61): error: invalid storage class for a template declaration
    1> inline template mpfr::mpreal ei_random()
    1> ^
    1>
    1>C:\mpfrc++\mpreal_eigen.h(80): error: invalid storage class for a template declaration
    1> inline template mpfr::mpreal ei_random(const mpfr::mpreal a, const mpfr::mpreal b)
    1> ^

  29. John
    Posted February 11, 2011 at 6:29 am | #

    By the way, this is not restricted to Intel’s compiler, Microsoft’s C/C++ Compiler Version 15.00.30729.01 for x64 also fails with the error below:

    mpreal_eigen.h(51) : error C2143: syntax error : missing ‘;’ before ”template<''
    mpreal_eigen.h(56) : error C2143: syntax error : missing ';' before ''template<''
    mpreal_eigen.h(61) : error C2143: syntax error : missing ';' before ''template<''
    mpreal_eigen.h(80) : error C2143: syntax error : missing ';' before ''template<''

    • John
      Posted February 11, 2011 at 6:37 am | #

      I found a fix: removing the inline keyword from each of those four lines makes the code compile!

      However, I wonder if there is any side effect?

      • John
        Posted February 11, 2011 at 6:48 am | #

        With no link-time errors

        • Posted February 11, 2011 at 9:15 am | #

          Initially I didn’t use inline for those four functions (since Eigen had no such rule for internal scalar types).

          Then Igor Krivenko reported that this disables mpreal_eigen.h inclusion in multiple cpp-files along with g++.

          Eigen also changed their plugin-rules at that time – so inline was introduced. Back then were no problems with MSVC and Intel compilation.

          Are you able to include mpreal_eigen.h in multiple cpp files now without inline + MSVC + Intel?

          I’m away from my dev. environment now – I can re-check g++ on Monday only.

          It is all down to how different compilers support inline+template function definition in the header.

          • John
            Posted February 12, 2011 at 12:56 am | #

            Update: If I change this:

            inline template <>

            to this

            template <> inline

            Now the code compiles with Intel’s C++ compiler 11.1 Win x64

  30. John
    Posted February 11, 2011 at 11:17 am | #

    I only include it in a single cpp file. I have not tried including it in several files.

    Nonetheless, the problem it’s a syntax error. Maybe inline can still be used for those functions but differently.

  31. John
    Posted February 12, 2011 at 7:35 am | #

    More problems with Eigen & MPFR C++

    When I try to assign the result of a coefficient-wise operation like pow:

    typedef Eigen::Matrix<mpfr::mpreal, Eigen::Dynamic, Eigen::Dynamic> EigenMatrixMPReal;
    ...
    EigenMatrixMPReal row_dest, row_i;
    ...
    row_dest = row_i.cwise().pow(mpfr::mpreal(10.0));

    The compilation dies with the error below. However, if I don’t do the assignment, the code compiles fine:

    row_i.cwise().pow(mpfr::mpreal(10.0)); // this doesn't cause compilation errors

    Changing from mpfr::mpreal(10.0) to 10.0 doesn’t make any difference

    I’m using eigen 2.0.15 (latest stable)

    Why is this happening?

    — John

    1>C:\Eigen\Eigen/src/Array/Functors.h(141): error: more than one instance of overloaded function "Eigen::ei_pow" matches the argument list:

    1> function "Eigen::ei_pow(int, int)"

    1> function "Eigen::ei_pow(float, float)"

    1> function "Eigen::ei_pow(double, double)"

    1> function "Eigen::ei_pow(long double, long double)"

    1> argument types are: (const mpfr::mpreal, const mpfr::mpreal)

    1> inline Scalar operator() (const Scalar& a) const { return ei_pow(a, m_exponent); }

    1> ^

    1> detected during:

    1> instantiation of "Scalar Eigen::ei_scalar_pow_op<Scalar>::operator()(const Scalar &) const [with Scalar=mpfr::mpreal]" at line 75 of "C:\Eigen\Eigen/src/Core/CwiseUnaryOp.h"
    .......

    • Posted February 12, 2011 at 12:34 pm | #

      @”Changing from mpfr::mpreal(10.0) to 10.0 doesn’t make any difference”.

      It seems like non-MPFR C++ bug. We need to report it to Eigen devs.
      I’ll get back to this problem on Monday.

      Could you try to use mpfr::mpreal("10.0"). If you use just mpfr::mpreal(10.0) then 10.0 is converted to double first and to mpreal after – so precision is lost (e.g. if you want to use 10.01).

      • Posted February 14, 2011 at 6:23 pm | #

        John, could you try to use the latest version of Eigen.
        It seems that they fixed bugs with custom-scalar types extensions in it.

        Also they ship their version of mpreal_eigen.h with latest eigen
        eigen\unsupported\Eigen\MPRealSupport

        • John
          Posted February 15, 2011 at 5:03 am | #

          According to their change log, MPFR C++ is no longer supported in Eigen 3. Also, it’s a beta version, and I prefer not to use beta versions.

          I also tried using mpfr::mpreal(“10.0”), but the error persists.

          Thanks

          • Posted February 15, 2011 at 9:19 am | #

            Ok, I’ll contact Eigen developers for answers.

  32. Dietrich
    Posted March 6, 2011 at 7:52 pm | #

    Hi Pavel,
    I have been using MPFR C++ for a while now and it works very well. Thanks a lot!
    I am using MPFR C++ with MPACK, for which Maho Nakata provides his own wrapper for complex numbers, similar in style to MPFR C++, but not quite as MSVC friendly. Since I am now also interested in using Eigen with complex multiprecision numbers, I was wondering whether you plan to extend MPFR C++ to cover complex numbers (MPC seems to be mature enough).

    Best regards,

    Dietrich

    P.S.: The Boost Math Toolkit now also supports mpreal for multiprecion calculations, see
    http://www.boost.org/doc/libs/1_46_0/libs/math/doc/sf_and_dist/html/math_toolkit/using_udt/use_mpfr.html
    Maybe you want to include a reference to this in your section on “Software using MPFR C++” ?

    • Posted March 6, 2011 at 8:59 pm | #

      Yes, I want to create mpcomplex (based on MPC) and mpint (big integer) numeric types for C++, so we will have all we need to do math in C++. Thank you for your request – it boosts priority of these tasks in my schedule. I’ll try to do this as soon as possible but I cannot promise exact dates.

      Wow, I didn’t know Boost introduced support for mpreal in their toolkit!
      These news totally made my day. Thanks for letting me know!

      • Dietrich
        Posted March 7, 2011 at 6:01 pm | #

        That’s great news. I am looking forward to your new library!

  33. Leonid
    Posted April 10, 2011 at 2:55 am | #

    Hi Pavel,
    I just tried using your wrapper with special functions from boost libraries and it looks like either your wrapper or boost bindings are flawed. Boost generally uses lexical cast in approximations of math functions (for example boost::lexical_cast<mpfr::mpreal>("12.2315")) and it looks like lexical cast fails to correctly create interpreter object through which it would stream data with << and >>.

    If you are interested in maintaining compatibility with boost libraries, you can try to reproduce this condition and see what is causing it. The exception is “bad lexical cast: source type value could not be interpreted as target”. Versions of libraries used: mpfr – 3.0.1; mpir – 2.3.1; boost – 1.46.1. mpfr built form Visual Studio 2010 using Brian Gladman’s project files. The error is present in all configurations (Release and debug on both Win32 and x64).

    Regards.

  34. Posted April 11, 2011 at 1:32 pm | #

    Hi Leonid,

    Thank you for your report.

    After quick tests I confirm this incompatibility. However I see no problem with mpreal – it complies with all (3) requirements of lexical_cast: Copy+Default Constructor and Input Streaming operator.

    Maybe I’m missing something, I need more time for deeper analysis.

    • Posted April 12, 2011 at 3:45 pm | #

      Although I still have no idea why default lexical_cast is not working, I’ve solved this problem by specializing it for mpreal type:

      namespace boost {
      	template<>
      	inline mpfr::mpreal lexical_cast(const std::string& arg)
      	{
      		return mpfr::mpreal(arg);
      	}
      }
      

      Then conversion works nicely:

      mpreal x = boost::lexical_cast<mpreal,std::string>("123.0125");
      

      It is much faster than conversion using streams (default lexical_cast).

      However mpreal supports direct conversion to/from string – I do not see necessity of lexical_cast for mpreal at all, eg:

      mpreal x = "123.0125";
      std:string s = x;
      
      • Tsai
        Posted May 31, 2011 at 11:27 am | #

        the lexical_cast problem is everywhere in boost. And it may still have other problems. This makes boost::math::special functions.hpp fails in general. Therefore, the boost::math::bindings of mpreal.hpp has serious problem to work into the entire boost.

        • Posted May 31, 2011 at 12:07 pm | #

          Yep, I was amazed by the fact that lexical_cast is slower than analogous code in Python and Java: http://stackoverflow.com/questions/1250795/very-poor-boostlexical-cast-performance

          Something wrong with the world, C++ is slower than Java/Python…..

          • Tsai
            Posted May 31, 2011 at 6:32 pm | #

            Today, I tested the boost::special_functions based on the mpfr::mpreal. It passed for all cases as shown in the last of this mail.

            I made the following modification.

            1. add the following code in mpreal.hpp

            namespace boost { template < > inline mpfr::mpreal lexical_cast(const std::string& arg)
            { return mpfr::mpreal(arg); } }

            2. change lexical_cast < mpreal ::mpreal > to lexical_cast < mpreal ::mpreal,std::string > in the entire boost.

            Then, I can get all answers correctly by a certain setting of complier.

            By the way, the lexical_cast use the std::istream target::operator>>(…) to cauch the std::iostream source::operator < <(…). Therefore, it is possible to avoid these by modifying istream& operator>>(istream &is, mpreal& v) in mpreal.cpp

            Test Code:
            #include < boost/math/bindings/mpreal.hpp >
            #include < boost/math/special_functions.hpp >


            int main()
            {
            mpfr::mpreal::set_default_prec(500); // 500 bit precision

            std::cout<<"cyl_bessel_k "<< std::setprecision(50) <<boost::math::cyl_bessel_k (mpfr::mpreal(5),mpfr::mpreal(7)) <<std::endl;
            std::cout<<"cyl_bessel_i "<< std::setprecision(50) <<boost::math::cyl_bessel_i (mpfr::mpreal(5),mpfr::mpreal(7)) <<std::endl;
            std::cout<<"cyl_bessel_j "<< std::setprecision(50) <<boost::math::cyl_bessel_j (mpfr::mpreal(5),mpfr::mpreal(7)) <<std::endl;
            std::cout<<"cyl_neumann "<< std::setprecision(50) <<boost::math::cyl_neumann (mpfr::mpreal(5),mpfr::mpreal(7)) <<std::endl;
            std::cout<<"factorial "<< std::setprecision(50) <<boost::math::factorial(3) <<std::endl;
            std::cout<<"acosh "<< std::setprecision(50) <<boost::math::acosh (mpfr::mpreal(2)) <<std::endl;
            std::cout<<"asinh "<< std::setprecision(50) <<boost::math::asinh (mpfr::mpreal(2)) <<std::endl;
            std::cout<<"atanh "<< std::setprecision(50) <<boost::math::atanh (mpfr::mpreal(.2)) <<std::endl;
            std::cout<<"cos_pi "<< std::setprecision(50) <<boost::math::cos_pi (mpfr::mpreal(.2)) <<std::endl;
            std::cout<<"sin_pi "<< std::setprecision(50) <<boost::math::sin_pi (mpfr::mpreal(.2)) <<std::endl;
            std::cout<<"cbrti "<< std::setprecision(50) <<boost::math::cbrt (mpfr::mpreal(8)) <<std::endl;
            std::cout<<"sinc_pi "<< std::setprecision(50) <<boost::math::sinc_pi (mpfr::mpreal(0.01)) <<std::endl;
            std::cout<<"bessel_j0 "<< std::setprecision(50) <<boost::math::detail::bessel_j0 (mpfr::mpreal(0.01))<<std::endl;
            std::cout<<"bessel_j1 "<< std::setprecision(50) <<boost::math::detail::bessel_j1 (mpfr::mpreal(0.01))<<std::endl;
            std::cout<<"bessel_y0 "<< std::setprecision(50) <<boost::math::detail::bessel_y0 (mpfr::mpreal(0.01))<<std::endl;
            std::cout<<"bessel_y1 "<< std::setprecision(50) <<boost::math::detail::bessel_y1 (mpfr::mpreal(0.01))<<std::endl;
            std::cout<<"bessel_k0 "<< std::setprecision(50) <<boost::math::detail::bessel_k0 (mpfr::mpreal(0.01))<<std::endl;
            std::cout<<"bessel_k1 "<< std::setprecision(50) <<boost::math::detail::bessel_k1 (mpfr::mpreal(0.01))<<std::endl;
            std::cout<<"bessel_i0 "<< std::setprecision(50) <<boost::math::detail::bessel_i0 (mpfr::mpreal(0.01))<<std::endl;
            std::cout<<"bessel_i1 "<< std::setprecision(50) <<boost::math::detail::bessel_i1 (mpfr::mpreal(0.01))<<std::endl;
            std::cout<<"bessel_jn "<< std::setprecision(50) <<boost::math::detail::bessel_jn (3,mpfr::mpreal(1)) <<std::endl;
            std::cout<<"bessel_yn "<< std::setprecision(50) <<boost::math::detail::bessel_yn (3,mpfr::mpreal(1)) <<std::endl;
            std::cout<<"bessel_kn "<< std::setprecision(50) <<boost::math::detail::bessel_kn (3,mpfr::mpreal(1)) <<std::endl;
            std::cout<<"lgamma "<< std::setprecision(50) <<boost::math::lgamma (mpfr::mpreal(0.55)) <<std::endl;
            std::cout<<"tgamma "<< std::setprecision(50) <<boost::math::tgamma (mpfr::mpreal(0.25)) <<std::endl;
            return 0;
            }

          • Posted May 31, 2011 at 7:19 pm | #

            @”Therefore, it is possible to avoid these by modifying istream& operator>>(istream &is, mpreal& v) in mpreal.cpp”

            Please advise how to modify istream& operator>>(istream &is, mpreal& v) .

        • Tsai
          Posted June 13, 2011 at 5:30 pm | #

          I use the following codes, there is no lexical_cast problem.

          istream& operator>>(istream &is, mpreal& v)
          {
          string tmp;
          is >> tmp;
          mpfr_set_str(v.mp, tmp.c_str(),mpreal::default_base,mpreal::default_rnd);
          return is;
          }

          • Posted June 14, 2011 at 9:52 am | #

            Seems nice, simplification of existing code to bare minimum – I’ll include it into mpreal class.

            However I still don’t see what is wrong with the existing code.

          • Tsai
            Posted June 14, 2011 at 7:07 pm | #

            Thank you for providing your excellent mpfrc++.
            Right now, your mpfrc++ works perfectly on my computer.
            These include the boost/math/special_functions and boost/numeric/ublas (I actually test my own version of ublasJama)
            That is amazing. Thank you again.

            I want to share my experimences.
            1. I comment the template operators in mpreal.hpp. I guess they are desigend for operators involving float, and thus I add float operators in mpreal.h
            2. The boost uses std::sqrt() and std::abs(). Therefore, I change mpfr::sqrt() and mpfr::abs() to namespace std.
            3. And the lexical_cast problem is fixed as in the last post.

            These are just ad-hoc solutions for mpreal in boost. The best solutions are up to the designers of mpfrc++ and boost

          • Tsai
            Posted June 10, 2012 at 7:35 pm | #

            I tried to combine the latest version of mpreal, Eigen 3.0.5, and boost::math 1.49.0. It seems the combination has been much improved. I tried to keep Eigen and boost::math as unchanged as possible while make three little changes for mpreal as follows:

            1. Simplifying operator>> as previously mentioned. I believe there is still some problems about lexical_cast in boost.

            2. Adding float version of operators, constructors, and member functions according to the same functions of double version. In boost, there are a lot of codes like “(T)a+0.5f with T=mpreal”, which require this modification.

            3. There are two conflicts between dmalloc and boost::math::special_functions. Although I have tried to fix them for some days, I just can fix one of them (dual is_initialized() in both dmalloc and boost) and cannot find the other one. When I cancel the dmalloc in mpreal, everything just becomes fine. Therefore, I will be very glad if you can provide any comment or suggest about how to work around the dmalloc while keeping safety of memory.

            Finally, I want to report that a very minor change about type consistency for the ?: operator has to be done for boost.

          • Posted June 11, 2012 at 3:32 pm | #

            Hi Tsai, thank you for you suggestions.

            However 1 and 2 are already implemented in mpreal.
            Please download the latest version.

            Algorithms in boost::math & special functions are heavily targeted for ‘double’ arithmetic – Pade approximations, constants, etc. If you want to use mpreal with boost – then most of the code in boost::math should be rewritten to be truly scalar-invariant and generic.

            Otherwise this combination won’t give high precision results even though mpreal is used. Since now boost::math is correct only for ‘double’ & ‘float’ types.

            Please check the latest mpreal for 1 and second points and let me know the results.

  35. valdes
    Posted May 8, 2011 at 1:15 am | #

    Dear Mr Holoborodko

    not long ago albeit a newbie to OOP I found myself engaged in multiprecision calculus and your work happily found
    appear to be a superb as quick start !
    In order to implement complex numbers I boldly wrote complex (mpreal) u = new complex (mpreal) [xxx];
    and all the ariphmetics remained alike but I found complex exponent 16 digits precision if written in exponential
    form and of arbitrary precision if written as a sum of real and imaginary parts and the complex logariphm as well
    Likely, I was to write my own complex sqrt function.
    These things albeit no problem at all showed I might be having future troubles this way ahead .
    I will be deeply indebted if you share your ideas of what they may appear to be and what my actions
    should be in general cause I ‘ m a sort of newbie (hope not a noob though) in OOP.

    Sincerely yours Valdes Coosk , Vilnius.

    P S brackets enclosing mpreal type are of course correct ones . round brackets are used instead
    cause they aren’t lost unlike angle brackets

    • astakhov
      Posted March 14, 2016 at 1:40 am | #

      dear Valdes only problem I’ve noticed is that when you divide complex mpreal type numbers writing c= a/b generates an error and
      equivalent one c=a*conj(b)/(abs(b)*abs(b)) does not when you switch to the last 2010 version

  36. Isaia Nisoli
    Posted May 25, 2011 at 4:07 pm | #

    Dear Pavel,
    I’m using an old version of the Boost.Library UBLAS (1.42) and I’m programming a linear algebra program.
    The fact is that the program compiles fine, but at runtime, even if I don’t call the function L1Norm(), I get the following error
    ../init2.c:52: MPFR assertion failed: p >= 2 && p >1))

    See complete source code….

    I really cannot understand where the problem lies… the real problem is that, since I’m working with sparse matrices I made a strong use of iterators in the whole of my program, so if dereferencing an iterator gives rise to a problem I’m in a really bad situation 🙂

    Best wishes
    Isaia

    UPDATE:
    I’ve discovered that if I access the matrix by A(rowindex,colindex) the problem does not occur.
    The real problem is that accessing the matrix this way is way much slower than using iterators.

    UPDATE2:
    I also tried with the new libboost 1.46.1 and the wrapper for mpreal.
    But I still get the same error at runtime.

  37. Chaffra Affouda
    Posted July 19, 2011 at 10:08 pm | #

    Hi Pavel,

    Thanks for this very useful wrapper. I can compile my python extension successfully with pycxx but I get the following runtime error. Any idea what this mean?
    Thanks,
    Chaffra

    *** Process received signal ***
    Signal: Aborted (6)
    Signal code: (-6)
    [ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7fe2fb879c60]
    [ 1] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x35) [0x7fe2fa683d05]
    [ 2] /lib/x86_64-linux-gnu/libc.so.6(abort+0x186) [0x7fe2fa687ab6]
    [ 3] …_transfer_matrix.so(dlmemalign+0) [0x7fe2b5023f30]
    [ 4] /usr/lib/libmpfr.so.4(mpfr_set_prec+0xa2) [0x7fe2d4132dc2]
    [ 5] …_transfer_matrix.so(_ZN15transfer_matrix12OpticalLayer16refractive_indexEN2Py6ObjectE+0x1a8) [0x7fe2b500d558]
    [ 6] …_transfer_matrix.so(_ZN15transfer_matrix12OpticalLayerC2EPN2Py19PythonClassInstanceERNS1_5TupleERNS1_4DictE+0x288) [0x7fe2b500e598]
    [ 7] …_transfer_matrix.so(_ZN2Py11PythonClassIN15transfer_matrix12OpticalLayerEE21extension_object_initEP7_objectS5_S5_+0x18e) [0x7fe2b501410e]
    [ 8] /usr/bin/python() [0x48928d]
    [ 9] /usr/bin/python(PyObject_Call+0x44) [0x45d864]
    [10] /usr/bin/python(PyEval_EvalFrameEx+0x9be) [0x496c4e]
    [11] /usr/bin/python(PyEval_EvalCodeEx+0x145) [0x49d325]
    [12] /usr/bin/python(PyEval_EvalFrameEx+0x802) [0x496a92]
    [13] /usr/bin/python(PyEval_EvalCodeEx+0x145) [0x49d325]
    [14] /usr/bin/python(PyEval_EvalFrameEx+0x802) [0x496a92]
    [15] /usr/bin/python(PyEval_EvalCodeEx+0x145) [0x49d325]
    [16] /usr/bin/python(PyEval_EvalCode+0x32) [0x4ecb02]
    [17] /usr/bin/python() [0x4fdc74]
    [18] /usr/bin/python(PyRun_FileExFlags+0x90) [0x42c182]
    [19] /usr/bin/python() [0x4288a0]
    [20] /usr/bin/python(PyEval_EvalFrameEx+0x42be) [0x49a54e]
    [21] /usr/bin/python(PyEval_EvalCodeEx+0x145) [0x49d325]
    [22] /usr/bin/python(PyEval_EvalFrameEx+0x802) [0x496a92]
    [23] /usr/bin/python(PyEval_EvalCodeEx+0x145) [0x49d325]
    [24] /usr/bin/python(PyEval_EvalFrameEx+0x802) [0x496a92]
    [25] /usr/bin/python(PyEval_EvalCodeEx+0x145) [0x49d325]
    [26] /usr/bin/python(PyEval_EvalFrameEx+0x802) [0x496a92]
    [27] /usr/bin/python(PyEval_EvalCodeEx+0x145) [0x49d325]
    [28] /usr/bin/python(PyEval_EvalCode+0x32) [0x4ecb02]
    [29] /usr/bin/python(PyEval_EvalFrameEx+0x34d0) [0x499760]
    *** End of error message ***
    Aborted

    • Posted July 20, 2011 at 11:40 am | #

      Hi,

      Problem seems to be related to multi-threading, which is not supported in MPFR C++ at the moment. Although low-level MPFR supports multi-threading correctly.

      • Chaffra Affouda
        Posted July 20, 2011 at 11:21 pm | #

        Hi Pavel,

        Thanks for the answer. I am not very familiar with c++ but this is then related to a previous question. How do I set the precision in one (main) thread like you suggested in (Posted September 18, 2010 at 8:46 pm | #) so that my extension does not seg fault.

        Thanks

        • Posted July 21, 2011 at 9:19 am | #


          main()
          {
             mpfr::mpreal::set_default_prec(...); // set precision at the beginning of the thread
             // do all calculations after
             ...
          }

  38. Philippe Marti
    Posted August 25, 2011 at 6:33 pm | #

    Hello Pavel,

    I tried to move my code from mpfrc++ to nika. But I got some errors:

    1)
    External/nika/mpreal.h: In function ‘const mpfr::mpreal mpfr::random(unsigned int)’:
    External/nika/mpreal.h:3040: error: ‘urandom’ is not a member of ‘mpfr’

    The error goes away be exchanging the definition of random and urandom in mpreal.h

    2)
    External/nika/mpreal.cpp: In member function ‘std::string mpfr::mpreal::toString(size_t, int, mpfr_rnd_t) const’:
    External/nika/mpreal.cpp:374: error: ‘sprintf_s’ was not declared in this scope

    I’m using GCC (4.4.5) on linux and I think sprintf_s is only available for visual studio.

    3)
    I saw your message about nika on the Eigen list. Is it too early to move to it?

    Thanks for your help,
    Philippe

    • Posted August 25, 2011 at 11:25 pm | #

      Philippe,

      Thank you for your bug report!

      I’m working on compatibility problems – GCC support will be ready in a few days.
      Please stick with mpfrc++ until then.

      Sorry for inconvenience – nika is still in beta I guess.

    • Posted August 26, 2011 at 3:39 pm | #

      Bugs have been fixed – please try new version from repository.

      • Philippe Marti
        Posted August 26, 2011 at 4:52 pm | #

        Pavel,

        Compilation went smoothly now (with desactivated int64). Only got the following warning:

        External/nika/mpreal.cpp: In member function ‘std::string mpfr::mpreal::toString(size_t, int, mpfr_rnd_t) const’:
        External/nika/mpreal.cpp:374: warning: format ‘%d’ expects type ‘int’, but argument 3 has type ‘size_t’

        Thanks a lot!
        Philippe

        • Posted August 26, 2011 at 5:02 pm | #

          Fixed. BTW what happens if you activate int64?

          • Philippe Marti
            Posted August 26, 2011 at 5:08 pm | #

            Well I get lots of:

            External/nika/mpreal.h:135: error: ‘mpfr::mpreal::mpreal(uint64_t, mpfr_prec_t, mpfr_rnd_t)’ cannot be overloaded
            External/nika/mpreal.h:129: error: with ‘mpfr::mpreal::mpreal(long unsigned int, mpfr_prec_t, mpfr_rnd_t)’
            External/nika/mpreal.h:136: error: ‘mpfr::mpreal::mpreal(int64_t, mpfr_prec_t, mpfr_rnd_t)’ cannot be overloaded
            External/nika/mpreal.h:131: error: with ‘mpfr::mpreal::mpreal(long int, mpfr_prec_t, mpfr_rnd_t)’
            …..

            and related redefinitions errors and:

            External/nika/mpreal.h:111: error: ‘__mpfr_struct mpfr::mpreal::mp [1]’ is private
            External/nika/mpreal.h:1254: error: within this context

          • Posted August 26, 2011 at 5:15 pm | #

            Hilarious output!
            What is version of gcc you have?

          • Philippe Marti
            Posted August 26, 2011 at 5:20 pm | #

            Its gcc-4.4.5

            I can try on another machine…

          • Posted August 26, 2011 at 5:22 pm | #

            Mine is 4.4.3. I guess I have to dig into GCC x64 support more. Thanks for the help.
            Apparently MSVC is much easier on this extend.

          • Philippe Marti
            Posted August 26, 2011 at 5:38 pm | #

            I tried on another machine with gcc (4.1.2, 4.3.3, 4.4.4, 4.6.1) with mpf-2.2.1. I get exactly the same errors.

            I might have done something strange in my code if it works for you.

          • Posted August 26, 2011 at 5:52 pm | #

            Could you check the size of int types on your platform?

            printf("sizeof(long long int) = %d\n", sizeof(long long int));
            printf("sizeof(int64_t) = %d\n", sizeof(int64_t));
            printf("sizeof(long int) = %d\n", sizeof(long int));
            printf("sizeof(unsigned long int) = %d\n", sizeof(unsigned long int));

            Seems that sizeof(int64_t)==sizeof(long int)==8 which is problematic.

          • Philippe Marti
            Posted August 26, 2011 at 5:57 pm | #

            sizeof(int64_t) = 8
            sizeof(long int) = 8
            sizeof(unsigned long int) = 8
            sizeof(unsigned long int) = 8

          • Posted August 26, 2011 at 6:01 pm | #

            Yep, it is. Is your system x64? Or you compile your program as x64?

            Sorry to bug you with so many questions.

          • Philippe Marti
            Posted August 26, 2011 at 6:03 pm | #

            Don’t worry for the questions, it’s the least I can do to help!

            yes, these are x64 machines/systems.

          • Posted August 26, 2011 at 6:12 pm | #

            Well this is very different from MSVC and now I need time to investigate GCC specifics more.

            Nika already supports x64 on your system, regardless of MPREAL_HAVE_INT64_SUPPORT since long int is 64-bit.

            So, you have full-featured multiprecision support.

            I’ll come up with general solution soon. Thanks for the help!

          • Philippe Marti
            Posted August 26, 2011 at 6:14 pm | #

            Ok, thanks for you help. If I can do any tests or something just let me know.

          • Posted August 26, 2011 at 6:29 pm | #

            Actually I think I found solution – could you try latest version from the rep?
            Now it handles GCC better.

  39. Javier Daza
    Posted September 9, 2011 at 2:30 am | #

    Hi Pavel,
    I am trying to use your code but the compiler is unable to indentify ‘intmax_t’ and ‘uintmax_t’ variables within file mpfr.h:

    main.cpp
    C:\MPFRC++\mpir_mpfr\mpfr\Win32\Debug\mpfr.h(354) : error C2061: syntax error : identifier ‘intmax_t’
    C:\MPFRC++\mpir_mpfr\mpfr\Win32\Debug\mpfr.h(356) : error C2061: syntax error : identifier ‘intmax_t’
    C:\MPFRC++\mpir_mpfr\mpfr\Win32\Debug\mpfr.h(357) : error C2061: syntax error : identifier ‘uintmax_t’
    C:\MPFRC++\mpir_mpfr\mpfr\Win32\Debug\mpfr.h(359) : error C2061: syntax error : identifier ‘uintmax_t’

    What is going on?

    Note: I am using Visual C++ compiler in U++ framework

    Thank you.

    Javier

    • Posted September 9, 2011 at 11:08 am | #

      Javier,

      Comment this line in mpreal.h as temporary measure:

      #define MPREAL_HAVE_INT64_SUPPORT // int64_t, uint64_t support

      And please tell me what version of MSVC do you use – so I can fix incompatibility.

      UPDATE:
      I’ve made fixes for VCs older than 2010. Please download updated version.

      • Javier Daza
        Posted September 9, 2011 at 11:47 pm | #

        Pavel,

        Thank you. I have to admit that I am using VC++ 8.

        The solution you proposed works fine.

        Usage of VC++ 10: In another –more modern- PC I am using VC++ 10 (I think is the latest issue- so I guess that for that version VC++ 10 there will be no problems; is it correct?). I shall try with this compiler next week.

        Remark: I notice you have updated the binaries for VC++10: thank you, because my intention is to use VC++ 10.

        Remark: the example provided in the example.cpp file works fine (I guess!; at least it compiles and run ok).

        Allow me more questions:

        1.- Is it possible to use integer numbers with multi precision (a kind of mpint) ?
        2.- Can mpreal be used with the STL (for example with vector? I have checked it and it compiles.

        Many thanks.

        Javier

        • Posted September 11, 2011 at 11:35 am | #

          1. You can do bignum integer arithmetic with mpreal – integers are just subset of floating point numbers :).
          MPFR C++ is not optimized for integer arithmetic though.

          2. Yes, mpreal is suitable for STL – it has few specific features for efficient integration with STL, like optimized swap needed for algorithms. I use them together on a daily basis.

  40. Javier Daza
    Posted September 13, 2011 at 7:13 am | #

    Pavel,

    I have checked your VC++ 10 files (in Debug mode) and work fine. Thank you.

    Some questions concerning the different files (I am not using Visual Studio but another C++ programming tool: U++):

    1.- I notice that you have included .dll files; I have copied the .dll file -those within the ‘Debug’ folder- in the system32 and in the sysWOW64 sub folder within Windows folder; this works for ‘Debug’. But, if I wanted to use the ‘Release’ dll, how can I do it since both .dll (‘Debug’ and ‘Release’) have the same name?

    2.- Concerning the other files: .exp,.ilk., what are they for? Do they need to be located in a specific folder?

    Note: my operating system is Windows 7 64 bits.

    Thank you,

    Javier

  41. Vinayak
    Posted November 26, 2011 at 11:43 am | #

    Hi,

    I am trying to use MPFR C++ for a real-time application which involves huge number of dot-products of vectors (with very small values per dimension but a float type product).

    I got it to give me good results, but the time taken is very very large as per my requirements. I need computation speed of about 15 Hz. Could you suggest some method which could reduce the computation time?

    Regards,
    Vinayak

    • Posted November 28, 2011 at 9:15 am | #

      You could try extended precision 80-bits doubles or quadruple precision floats (128 bits).
      Both are supported in GNU gcc – long double and _float128.

      They give around 20 and 34 correct digits correspondingly. Operations with them are generally faster comparing to arbitrary precision MPFR.

  42. felix
    Posted December 26, 2011 at 11:10 pm | #

    You write that “Only final result are rounded to the precision of target variable (x = t3).”. But in mpreal.h, in the definition of operator=(const mpreal&), the precision of the argument is taken as the new precision.

    • Posted December 27, 2011 at 11:30 am | #

      Yes, you are right, this was a mistake in description. I’ve changed assignment operators in MPFR C++ only recently to make them more consistent. If you want to assign one number to another it is only natural to assume that is “everything” is being copied, not rounded.

      However treatment of intermediate evaluations (which is the most important part) stayed the same:
      MPFR C++ keeps correct accuracy of intermediate calculations during complex expression evaluation in order to obtain precise final result. Other libraries calculate intermediate results with the precision of final variable or round them to some not obvious to user precision which is independent from precision of arguments as well as from precision of final variable. This could lead to significant accuracy decreasing of final result.

  43. slee
    Posted January 8, 2012 at 1:29 am | #

    How can I convert double to mpreal or convert mpreal to double ?

    //code
    mpreal x = “10”;
    double y = x; // error

    double a = 10;
    mpreal b = a; //error

    • Posted January 8, 2012 at 1:22 pm | #


      mpreal x = “10″;
      double y = x.toDouble();

      Second code snippet is working fine without errors. Could you explain what kind of error do you get?

  44. Li Dong
    Posted January 16, 2012 at 3:24 pm | #

    Hi, Pavel,

    I am working on a Lagrangian advection numerical scheme in C++, which seems need high precise floating-point calculation, so I would like to try MPFR C++ out. I have downloaded it, and in its directory, I “make” and get the following errors:

    g++ -c example.cpp
    In file included from example.cpp:2:
    mpreal.h: In member function ‘const __mpfr_struct* mpfr::mpreal::mpfr_srcptr() const’:
    mpreal.h:1407: error: expected `’ before ‘[’ token
    mpreal.h:1407: error: expected `(‘ before ‘[’ token
    mpreal.h:1407: error: expected primary-expression before ‘[’ token
    mpreal.h:1407: error: expected primary-expression before ‘:’ token
    mpreal.h:1407: error: expected `]’ before ‘:’ token
    mpreal.h:1407: error: expected `)’ before ‘:’ token
    mpreal.h:1407: error: expected ‘;’ before ‘:’ token
    mpreal.h:1407: error: expected primary-expression before ‘:’ token
    mpreal.h:1407: error: expected `;’ before ‘:’ token
    make: *** [example.o] Error 1

    I am in Mac Pro with g++ 4.2.1. Also I tried it out in a virtual Ubuntu with g++ 4.6.1 with the errors:

    g++ -c example.cpp
    In file included from example.cpp:2:0:
    mpreal.h: In member function ‘const __mpfr_struct* mpfr::mpreal::mpfr_srcptr() const’:
    mpreal.h:1407:69: error: expected ‘<’ before ‘<:’ token
    mpreal.h:1407:69: error: expected type-specifier before ‘’ before ‘<:’ token
    mpreal.h:1407:69: error: expected ‘(’ before ‘<:’ token
    mpreal.h:1407:71: error: expected identifier before ‘:’ token
    mpreal.h:1407:88: error: expected ‘]’ before ‘;’ token
    mpreal.h: In lambda function:
    mpreal.h:1407:88: error: expected ‘{’ before ‘;’ token
    mpreal.h: In member function ‘const __mpfr_struct* mpfr::mpreal::mpfr_srcptr() const’:
    mpreal.h:1407:88: warning: lambda expressions only available with -std=c++0x or -std=gnu++0x [enabled by default]
    mpreal.h:1407:88: error: expected ‘)’ before ‘;’ token
    make: *** [example.o] Error 1

    Cheers,

    Li

    • Posted January 16, 2012 at 3:37 pm | #

      Download new version, this bug was fixed few days ago.

      • Li Dong
        Posted January 16, 2012 at 3:48 pm | #

        Where is the new version? I have downloaded it from the above “Download” link.

        Thanks!

        • Posted January 16, 2012 at 3:52 pm | #

          Use same download link :). I’ve replaced files.

          • Li Dong
            Posted January 16, 2012 at 4:06 pm | #

            Sorry, I have downloaded it again and the same error result. Could you put the link in your reply?

          • Posted January 16, 2012 at 4:21 pm | #

            Download one more time please. I’ve tested in on Ubuntu and fixed bug.

          • Li Dong
            Posted January 16, 2012 at 4:26 pm | #

            Yes, works now~ Thanks!

          • Posted January 16, 2012 at 4:27 pm | #

            Ok, great, let me know on whether it was helpful for your research

          • Li Dong
            Posted January 16, 2012 at 4:30 pm | #

            By the way, how do I use it? Put it under my source directories? Or any other suggested usage?

  45. Li Dong
    Posted January 16, 2012 at 5:06 pm | #

    Hi Pavel,

    I have just tried out MPFRC++, and it really helps me by giving me the right answer in the calculation of the intersection between a great-circle arc and latitudinal line segment, which is wrong at normal “double” calculation. But the computing slows down considerably (set the default precision to 128 following the example).

    Cheers,

    Li

    • Posted January 16, 2012 at 5:12 pm | #

      Thank you for feedback.

      @ But the computing slows down considerably

      If 128bits are sufficient for you – you could try optimized 128-double libraries. They are faster than MPFR which is targeted for arbitrary precision. I believe gcc has one of that kind under __float128 or similar name.

  46. Marco
    Posted January 20, 2012 at 4:41 am | #

    Spelling error i think:
    s/Doug Lee/Doug Lea/

  47. Jirka
    Posted February 8, 2012 at 11:38 am | #

    Hi Pavel,

    I plan to use MPFRC++ together with Eigen. So far it looks very promising:-)

    However, I have bumped into one problem

    When trying to compile


    typedef Matrix<mpreal, Dynamic, 1 > mpfr_vector;
    mpfr_vector y;
    mpreal t;

    t = y.cwise().abs().minCoeff();

    I’m getting error (gcc 4.4.3)

    error: ‘class Eigen::Matrix’ has no member named ‘cwise’

    I’m trying to find minimum mpreal value of |y|.

    Is it a known limitation? Can

    #include <unsupported/Eigen/MPRealSupport>

    be updated to support cwise?

    Thanks a lot!
    Jirka

  48. Jirka
    Posted February 9, 2012 at 3:58 am | #

    Hi Pavel,

    thanks a lot for the quick reply! I have tried both ways and both are working just fine.

    It’s obviously my mistake. I was starting with Eigen2 but I have found out that “unsupported/Eigen/MPRealSupport” is not part of my Eigen2 installation. So I have downloaded Eigen3 but I didn’t check if cwise operator is still there.

    Thanks a lot for the clarification. Eigen together with MPFRC++ gives programmers a lot of power. I’m converting a program written with ARPREC to MPFR and I’m amazed how easily it goes with the right libraries:-)

    Thanks
    Jirka

    • Posted February 9, 2012 at 9:40 am | #

      You are right – Eigen is amazing library. I’m using it on a daily basis in several projects – and never complained. It is nice example what can be done with meta-programming methodology in C++.

      MPFR is another gem (ARPREC is a way behind, imho). It was only natural to marry them together:-).

      Lately I’ve made one further step – to blend MPFR & Eigen & MATLAB. Here is my Multiprecision Computing Toolbox for MATLAB.
      It uses latest MATLAB’s OOP capabilities to overload built-in functions with multiprecision analogs, so that all computations in MATLAB can be done with any desired accuracy without source code changes.
      (I thought it might be of some interest to you from what I see in your profile in LinkedIn)

      P.S.
      I plan to make updates to MPRealSupport shortly – I’ll let you know.

      • Jirka
        Posted February 10, 2012 at 8:12 am | #

        Yes, ARPREC is definitely behind MPFR.

        I’m about to convert PSLQ routines from ARPREC package to MPFR&Eigen. The current PSLQ implementation is using it’s own simple matrix class + ARPREC arithmetic. With MPFR&Eigen the conversion is very smooth, I need to rewrite only portions of the code.

        I have checked your Multiprecision Computing Toolbox for MATLAB and it’s really impressive. I have used MATLAB at university a lot and I liked it. As the student I had free access to it. Things have changed when I have left the university. The price tag is too high. Same applies to Mathematica. It’s a pity. Nowadays I use mainly open source software….

        > I plan to make updates to MPRealSupport shortly – I’ll let you know.
        Great:-)

        Thanks
        Jirka

        • Posted February 10, 2012 at 9:33 am | #

          This might be helpful: An implementation of PSLQ in GMP

          I love open source too. However I cannot solve puzzle on how to create self-sustainable open source projects yet. Constant improvement, timely bug fixing, user support are all possible only if development is well funded.

          As i see long-lived well developed open source can only exist as part of business model (Linux – 80% is developed by commercial companies, Mozilla, Chrome) or university project (Eigen, MPFR, etc.) .
          And actually universities are no different from usual business – they charge clients (students) for tuition and fund “in-house” open source projects to promote their brand and recognition to attract more students.

          As long as we live in capitalism system – no “true” self-sustainable open source project is possible I guess.

          • Jirka
            Posted February 11, 2012 at 10:15 am | #

            Hi Pavel,

            I’m aware of Paul Zimmermann’s PSLQ implementation. Last time I have tested it was just a simple implementation and it was not as good as PSLQ distributed by prof. Bailey. After all, prof. Bailey has designed PSLQ. That’s why I’m attempting to rewrite Bailey’s implementation to use MPFR.

            Regarding the open source – I agree that long-lived well developed open source needs some commercial support. I do maintain 5 Fedora rpm packages and the ones with most active development going on are the ones developed by universities. 2 packages are developed by individuals and while they are very responsive to my suggestions they have simple no time for anything more than maintenance.

            I’m about to finish a random number generator open source package. It has been fun to work on it. I however struggle with the last mile – clean-up the code and document it well. Let’s hope that it will have some resonance….

            Jirka

  49. Jauhien
    Posted April 16, 2012 at 12:49 am | #

    Hi Pavel,
    I’m planning to use your library in one little scientific project. I use gentoo and I think it would be great to use your library in standard way (that is write an ebuild for it and may be upload it to overlay then), but I need to know two things for do so:
    1. What is your versioning schema? I haven’t found any version number of mpfr c++.
    2. What is the liecense? I’ve found only “MPFR C++ is free for usage in free projects.”

    Thanks for response.

    UPDATE:
    I’ve found license in zip file.
    So only question about version number is actual.

    • Posted April 16, 2012 at 9:29 am | #

      Hi Jauhien,

      Basically license is “MPFR C++ is free for usage in free projects on the basis of clear attribution”.
      If project is commercial – lets discuss this over email: pavel@holoborodko.com

      No version control, library is pretty small and I maintain compatibility while upgrading.
      You can refer to the date of last change if it is Ok – see news above.

  50. Posted May 23, 2012 at 12:42 am | #

    Pavel,

    I’ve been looking for an easy to use solution for arbitrary precision calculation for my fractal programs as there is a limit to the depth of zoom achievable. I’ve had a look at some alternatives which supported complex numbers and the implementation of the interface looked over complicated, so I looked at this wrapper and it is nice and simple in comparison, however with no apparent support for complex numbers.

    It turns out that I needn’t have worried as a test program showed that using std::complex just works, even with the complex functions e.g. std::cos, so there is no need for a complex number wrapper at all. I haven’t tried it with the boost versions of complex functions that are present with g++ 4.4 but not with MSVC2010 but I don’t anticipate any problems.

    Now that I’ve established the viability of adding arbitrary precision to my software I added the requirement for automatic switching from long double to arbitrary precision and back again for version 3.0. As version 3.0 is a major upgrade I don’t envisage incorporating MPFRC++ for several weeks.

    When I have incorporated MPFRC++ I’ll add a link to here from my blog, I may even add link and blog post before then.

    Thanks for hard work.

    regards,
    Mark Eggleston

    • Posted May 23, 2012 at 2:53 pm | #

      Mark,

      Thank you for letting me know about your application of MPFR C++. Your fractal images are beautiful!

      As for std::complex<mpreal> – I do not recommend using it as it is. Although it is intended to be invariant of real scalar – yet functions are implemented using usual double precision constants here and there. Which results in lower overall precision of the result. Last time I checked MSVC’s code for std::complex I found it unacceptable for serious calculations with guaranteed accuracy. Check carefully functions code before using it.

      Same goes for boost – many special functions are implemented using few terms of series/fractions approximation with double precision constants to put aside that many such algorithms are not applicable for arbitrary precision computing at all.

      @When I have incorporated MPFRC++ I’ll add a link to here from my blog, I may even add link and blog post before then.
      I would greatly appreciate this and will include link to your site from the page in return.

      • Posted May 23, 2012 at 6:59 pm | #

        Pavel,

        Thanks for the advice I hadn’t considered the use of constants in std::complex.

  51. Tsai
    Posted June 11, 2012 at 9:19 pm | #

    Pavel,

    The other conflict between dlmalloc and boost::math is the #define gm in dlmalloc.
    It will be a dream to have a truly scalar-invariant and generic mpreal special functions.
    Right now, the ad-hoc solution is tested to be accurate at least to 50 dicimal places.

    best regard

    • Posted June 12, 2012 at 9:20 am | #

      Actually dlmalloc is optional to mpreal, just exclude it from the compilation. It is disabled by default and I just forgot to remove it from the bundle.

      I’ve been working on generic numerical math library (linear algebra, ODE, integration, optimization, special functions, real and complex) for a few years now.

      The problem is that I have no funding, and I try to develop it as a commercial product in order to bring food on my table (without any success to be honest). Here is the link if you are interested: Multiprecision Computing Toolbox for MATLAB.

  52. Pau
    Posted June 21, 2012 at 10:31 pm | #

    Hi Pavel,

    just one small comment: in the “Download” section, you say that

    MPFR (>= 2.3.1) and MPIR (>=2.0.0) (or GMP >=4.2.1) are needed for MPFR C++

    I think that in fact one needs MPFR >= 3.0, because your header file mpreal.h is using function ‘mpfr_set_zero’, which is not available in versions < 3.0 of MPFR.

    I have an older version of MPFR (2.4) in my system, and the provided example (example.cpp) fails to compile due to this issue. Arrggg! I will have to upgrade my Ubuntu…

    Best,
    /P

    • Posted June 22, 2012 at 1:48 pm | #

      Hi Pau,

      I’ve fixed this incompatibility, sorry for (unintended) false advertisement. Also there are other improvements. Please re-download updated version.

      But, I would really recommend you to switch to the latest MPFR 3.0.0+patches, or even use trunk version 3.1.0.
      Since version 2.4 there were a lot of improvements and bug fixes.

      • Pau
        Posted June 22, 2012 at 4:04 pm | #

        Thanks for the quick fix.

        Still, after re-downloading MPFR C++ and re-compiling, I got a small compile error:

        mpreal.cpp:75: error: ‘MPFR_RNDN’ was not declared in this scope

        After looking through mpfr.h, I fixed this by simply changing MPFR_RNDN to GMP_RNDN.
        After this small change, the example compiles OK.

        I will follow your advice and upgrade to MPFR 3.x as soon as possible.

        • Posted June 22, 2012 at 4:26 pm | #

          Ok, great. I’ve changed MPFR_RNDN to GMP_RNDN everywhere.
          However in future MPFR developers will abandon GMP style and will switch to pure MPFR constants.

  53. Paulo Sherring
    Posted June 24, 2012 at 1:44 pm | #

    Hi there!
    I have a MATLAB routine that works perfectly. When I translated it to C equivalent, some discrepancies appeared. Then, I decided to use use some math lib, and just started using your lib, under VS2010, after some awful results I was getting with regular double cmath lib.

    Altough very intuitive – cheers for that! -, I am having some trouble with convertions.
    the code is very straight forward:

    mpfr::mpreal Tsr (Ts);

    I have a function that receives a double Ts, timestep. The passed value is 250, or 0.000250. When creating a mpreal from it, I get :
    + DebugView “0.0002500000118743628263”
    Ts 0.00025000000000000001
    (out from vs2010 debugger)

    What am I missing? Any thoughts?
    By the way, this is some sort of intermitent problem, some convertions are completly perfect 🙁
    Is there a way to set to zero the last digits?
    I mean, if I know that the only 6 decimal digits are significant, is there a way for me to set to zero those last decimal digits?
    Thanks in advance!!
    Paulo Sherring.

    • Posted June 24, 2012 at 6:34 pm | #

      Dear Paulo,

      There is no bug. MPFR numbers are represented in base 2, and number 0.00025 (as many many others) is not exactly re-presentable in base 2. Thus it is rounded to the nearest combination of negative powers of 2. This is usual issues of floating point arithmetic. MPFR provides much better approximation by powers of 2 comparing to usual double.

      BTW, here is toolbox which allows conversion of existing MATLAB programs to use arbitrary precision arithmetic:
      Multiprecision Computing Toolbox for MATLAB

      • Paulo Sherring
        Posted June 24, 2012 at 10:46 pm | #

        That I understand. But as you can see, double is having a better performance compared to MPFR.
        In deed, sometimes the conversion runs OK and some times doesnt. Sometimes, MPFR succeeds to have a better representation, moving the incorrectness from the 16th decimal digit to the 18th or so, with 64 bits precision.

        Any other thoughs? I am downloading the pointed program right now!
        Thanks again!
        Paulo Sherring.

        • Posted June 24, 2012 at 11:17 pm | #

          What precision do you use for mpreal? Try 128 or 256 bits :).

          MPFR uses a little different format to store numbers – it cannot be compared directly to double even for the same precision.
          MPFR manual has section on what should be done for such comparison to be valid. As far as I remember, it includes normalization, exponent shifting, and some other steps.

          • Paulo Sherring
            Posted June 24, 2012 at 11:38 pm | #

            I did try with higher precision. It still initialized the mpfr to a wrong value. I mean, the representation achieved with mpreal was much less precise than double representation. The parameter I am evaluating is the debug value shown – might not be the best,but, does facilitate for me, since comparing real numbers is much more natural for most common human, like I, hehehe.
            The use I intend for mpreal is the following:
            An interpreter uses double as interface. But the calculations that follows the interpreter are much sensitive, so I wanted to use a better precision representation, that allowed me to do better math. And then convert back to double the obtained results to proceed to integration numeric integration.

            Why – you may ask – proceed the numeric integration with double. Only the intermediary code uses squares, nth roots and etc, which are prone to hugh loss of data. But, well, the program is still a work in development, and it might change. Or not, since I profoundly wish to present this work by August 😛

            Paulo Sherring.

          • Posted June 25, 2012 at 11:29 am | #

            Hi Paulo,

            Today I’ve tested your example. Everything works fine in my settings. See screenshot below:

            Could you provide more information on your environment – VC2010 compiler settings, MPFR version, example of your code. Do you use float or double? What precision do you use for mpreals?

  54. Paulo Sherring
    Posted July 1, 2012 at 3:07 am | #

    For some unknown reason, I was getting – from time to time – this bizarre conversions. In the end, I found out that using MP was not for real time applications such as my, since it the code execution time became much longer than with regular FP, something I could not afford. 🙁
    I will keep experimenting with your MPFR C++.
    And thanks for all the fish!

  55. Posted July 4, 2012 at 11:22 am | #

    Hi Pavel,

    I’m looking for a way to do calculations with non-integer numbers that would *always* yield the same results, even with other compilers, other architectures etc. You cannot achieve this by using floats or doubles, so I’m trying to find a library that lets you do that, even if I need to lose a little bit of performance. The high precision of the results is not really important for me, the result should just always and everywhere be the same.
    Is mpfr (hence mpfrc++) a good solution for what I’m looking for? According to “with correct rounding” from the GNU MPFR description, it seems like it is, but I would like to be sure before I change all my code to use mpreal…

    And if it is, do you have better performances by setting the precision to a lower value, or is it always the same?

    Sorry if these questions are already answered in the previous comments, but there are a lot of them and they are not really classified by topic, so hard to search in :p

    Thank you in advance.

  56. Matthew
    Posted July 18, 2012 at 3:01 am | #

    Dear Pavel,

    BOOST announced a couple of versions ago that they have included support for mpreal. (Great news!)

    Has this support been maintained? On version 1.48.0, I am trying to use the binding for mpreal, but get “ambiguous overload” compile errors for various operators.

    Is only an older version of mpreal supported? Is mpreal only supported for older version of BOOST ?

    Thank you! and great wrapper!

    • Matthew
      Posted July 18, 2012 at 5:41 am | #

      The same compile errors (“ambiguous overload ….” ) persist with BOOST 1.50.0 and the current version of MPFRC++.

  57. John
    Posted September 26, 2012 at 8:53 pm | #

    Hi Pavel

    I found a small bug in operator= for const char*. The precision of the temporary variable can be less than that of the mp variable. Therefore you will lose precision when making an assignment under these circumstances. I rewrote the function and it now works correctly. Here is the code for you to check:

    mpreal& mpreal::operator=(const char* s)
    {
    mpfr_t t;

    #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
    set_custom_malloc();
    #endif

    mpfr_init2(t, mpfr_get_prec(mp));

    if(mpfr_set_str(t, s, default_base, default_rnd) == 0)
    {
    mpfr_set(mp, t, mpreal::default_rnd);
    mpfr_clear(t);

    MPREAL_MSVC_DEBUGVIEW_CODE;

    }else{
    mpfr_clear(t);
    }

    return *this;
    }

    I noticed that I could assign a std::string with the = operator (even though I could not see the function) and the compiler would not complain. This also suffered from the same problem, so I adapted the above function for std::string and this works fine too:

    mpreal& mpreal::operator=(const std::string& s)
    {
    mpfr_t t;

    #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
    set_custom_malloc();
    #endif

    mpfr_init2(t, mpfr_get_prec(mp));

    if(mpfr_set_str(t, s.c_str(), default_base, default_rnd) == 0)
    {
    mpfr_set(mp, t, mpreal::default_rnd);
    mpfr_clear(t);

    MPREAL_MSVC_DEBUGVIEW_CODE;

    }else{
    mpfr_clear(t);
    }

    return *this;
    }

    Best regards,

    John

    • Posted October 9, 2012 at 9:39 am | #

      Dear John,

      Thank you very much for your contribution!
      Meanwhile I have re-designed mpreal to be one-header library, with many other bug fixes and improvements.

      I will release new version in a few days with all the improvements (including your bug fix and reported by other users).

  58. Posted October 19, 2012 at 3:36 pm | #

    Here is update for everyone subscribed to the MPFR C++ page.

    Today I have released new version, which includes major improvements and bug fixes.
    I’ve modified it to be thread-safe, removed static variables to escape “hell of unpredictable order of global variables initialization” ,
    added specialization for std::numeric_limits, fixed bugs among other things.

    Now MPFR C++ is a single header library, which is easy to use.

    API compatibility with older versions should be preserved.

    I would appreciate tests, comments, suggestions.

  59. Matthew
    Posted November 9, 2012 at 9:22 am | #

    Hey Pavel,

    How should we cite MPRC++ if we use it for our scientific research?

    • Posted November 9, 2012 at 11:11 am | #

      Actually I have no idea, maybe something like this (?):

      @misc{mpfrcpp,
      author = {P. Holoborodko},
      title = {MPFR C++},
      howpublished = {http://www.holoborodko.com/pavel/mpfr/}
      year = {2008-2012}
      }

      Is there any special way to cite software library, published on the web? Or maybe just cite this webpage.

      • Matthew
        Posted November 9, 2012 at 10:36 pm | #

        Yeah, that’s basically what I have so far. I don’t know of any special way to cite software libraries from the web. Even the BibTeX entry for Boost libraries looks like what you wrote.

  60. Malko Bravi
    Posted November 10, 2012 at 12:44 am | #

    Hi Pavel,

    I would like to format the output from my program using std::ios_base::precision and std::ios_base::setf.
    When using mpreal the first one works, but instead of counting the precision as the number of digits after the dot (as it does for a double), it counts all the digits, including those before the dot.
    The second one instead doesn’t work at all.

    In other words, what I would expect is for the output of this simple example program to be the same in format:


    #include <fstream
    #include "mpreal.h"

    using namespace mpfr;
    using namespace std;

    int main()
    {
    mpreal::set_default_prec(128);
    ofstream out;
    double h[5];
    mpreal m[5];

    out.precision(15);
    out.setf(ios::scientific,ios::floatfield);
    out.open("output");

    for (int i = 0; i < 3; i++)
    {
    h[i] = 100. / (i+7);
    m[i] = 100. / (i+7);
    }

    out << h[0] << "\t" << h[1] << "\t" << h[2] << endl;
    out << m[0] << "\t" << m[1] << "\t\t\t" << m[2] << endl;

    out.close();
    return 0;
    }

    The output, instead of being two identical lines (at least in format), looks like this:

    1.428571428571429e+01 1.250000000000000e+01 1.111111111111111e+01
    14.2857142857143 12.5 11.1111111111111

    What I don’t undestand is that you just friended the ostream and istream operator<<, so I'd expect it to work normally. Is there some way to get the job done without losing precision by using mpreal::toDouble()?

    Thank you for the fantastic wrapper!

    • Posted November 12, 2012 at 3:06 pm | #

      Hi,

      Currently MPFR C++ doesn’t support std::ios_base::setf – will include this in next version.
      Now you can use toString(format) for detailed format adjustment.

  61. fpghost
    Posted November 23, 2012 at 1:07 am | #

    I would like the output to be compatiable with Mathematica, so no ‘e’ scientific notation, what must I do to achieve this? What options are there for `format` in `toString(format)`? I really need something like 2.234234234234*10^-23 or maybe 2.32434234324E-23 is also OK.

    • Posted November 23, 2012 at 10:13 am | #

      General format specification is: "%[[width].[precision]]RN[e,f,g]". In your case format might look like: "%RNe"

      For detailed explanation please check “Formatted Output Functions” chapter in MPFR manual.

  62. fpghost
    Posted December 4, 2012 at 12:33 am | #

    thanks Pavel.

    I am using your wrapper mpreal with an ode solver (odeint) and on my 32bit desktop linux the code works great and gives me a binary that does what I want. However upon compiling it on a 64-bit server with the same gcc (gmp and mpfr versions same too) I get errors like “error: call of overloaded ‘mpreal(long long int)’ is ambiguous” I was wondering if you might know why? maybe this constructor doesn’t exist, but somehow some kind of casting is done implicitely on my 32bit desktop, but gives these errors on the 64bit server?

    • fpghost
      Posted December 4, 2012 at 4:10 am | #

      temporarily I added some additional constructors into the mpreal.h header, and the code now compiles on 64 bit system, although I’m not sure if it will handle things correctly. I just added constructors for “mpreal(const long long int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());” and defined as

      inline mpreal::mpreal(const long long int u, mp_prec_t prec, mp_rnd_t mode)
      {
      mpfr_init2(mp,prec);
      mpfr_set_si(mp, u, mode);

      MPREAL_MSVC_DEBUGVIEW_CODE;
      }

      and similarly for unsigned long long int. I’m not sure if mpfr_set_si, and mpfr_set_su are appropriate though?

      • Posted December 4, 2012 at 11:49 am | #

        I (and many other people) use mpreal on x64 Linux without such a problems.

        “long int” is of 64 bits on gcc already (and supported by mpreal). No “long long int” is required.

        Could you let me know which version of MPFR/GMP/GCC you are using?

        • fpghost
          Posted December 4, 2012 at 5:28 pm | #

          yes, unfortunately the ODE solving library I’m using, ‘odeint’, somewhere uses ‘long long int’ in the code, and this ultimately results in an mpreal being constructed as ‘mpreal (long long int)’. I guess on 32bit linux some implicit cast is done from ‘long long int’ to ‘long int’ and everything just works, but on 64bit it doesn’t and generates the “is ambiguous error”.

          I’m using gcc 4.6.3, mpfr 3.1.1, gmp 5.0.5. The version of linux on my desktop is 32 bit ubuntu 12.04, and on the server 64 bit red hat linux enterprise server edition.

          In the mean time I just implanted my own constructor into your “mpreal.h” as shown in my previous comment and the code now compiles and *seems* to work. Could you tell me if there is a better way to build such a constructor though? Is there a “mpfr_set_?” function that can handle ‘long long int’ better than “mpfr_set_ui” or “mpfr_set_si”?

          • Posted December 4, 2012 at 5:35 pm | #

            Functions “mpfr_set_ui/si” should be fine.
            Basically constructor for “long long int” should be equivalent to “long int” one.

            Do you get any errors when you compile your code (with “long long int” constructor in mpreal) on x32 system?

          • fpghost
            Posted December 4, 2012 at 7:10 pm | #

            [quote]Functions “mpfr_set_ui/si” should be fine.
            Basically constructor for “long long int” should be equivalent to “long int” one. [/quote]

            OK, that’s good, that’s what I’ve done.

            [quote]Do you get any errors when you compile your code (with “long long int” constructor in mpreal) on x32 system? [/quote]

            I don’t have access at the moment, but will give it a go soon and let you know.

          • fpghost
            Posted December 4, 2012 at 11:49 pm | #

            Actually with the new constructors (for ‘long long int’) I added in mpreal.h I do get compilation errors when run on the x32 system. Why is that? is it to do with MPREAL_HAVE_INT64_SUPPORT in your header, meaning you’ve already defined this constructor for x32 systems, so now my new constructor clashes? So for the 32x system you have effectively defined a constructor for `long long int` already which is why things just worked out of the box when I ran my code on my 32 bit desktop? whereas for x64, because of the fact that long int and long long int are the same thing, there was no reason for you to build a constructor that took long long int, as no one should be using this type.

          • Posted December 5, 2012 at 11:47 am | #

            “…whereas for x64, because of the fact that long int and long long int are the same thing, there was no reason for you to build a constructor that took long long int, as no one should be using this type.”

            Exactly. GNU GCC system makes porting from x32 to x64 a little bit messy. It automatically upgrades integer types to x64 bits, which could easily break code being ported.

            The best workaround for GCC would be to use types with explicit number of bits: int32_t, int64_t from stdint.h.
            Then move from x32 to x64 would be painless.

            However neither authors of MPFR nor developers of numeric libraries follow this standard using “long long int”, “long int”, “intmax_t” all of which means different things on x32 and x64 in GCC world.

            There is some macro-logic in mpreal.h which tries to make things smooth:
            (a) for x32 builds we define additional constructors for int64_t (aka “long long int” or “intmax_t” )
            (b) for x64 builds we remove constructors for such type since “long int” is already 64bit wide.

            Macro MPREAL_HAVE_INT64_SUPPORT plays only “suggestive” role, it is undefined automatically for x64 builds on GCC to avoid clash among integer types.

            The better way would be to detect bit resolution of all integer types at compile time (using macros or meta-magic similar to boost) and add suitable routines to mpreal class. This could easily grow to be more complex than mpreal itself :).

            Maybe I will come up with better solution in future versions, any suggestions are welcome.

  63. Peter
    Posted February 3, 2013 at 7:47 am | #

    How is the following code compiled?

    bool test = mpreal("1.0001") > 1

    I’m using code similar to this in a tight loop where I want to avoid memory allocation as much as possible. Looking through the mpreal header I only found this operator definition:

    friend bool operator > (const mpreal& a, const mpreal& b);

    Now i wonder how my code even get’s compiled since there is no:

    friend bool operator > (const mpreal& a, const int b);

    Is my mpreal automatically cast to an int for the comparison? Or is an mpreal automagically contructed from the “1” causing memory alloction?

  64. Brzezinski
    Posted February 5, 2013 at 6:00 am | #

    I am sorry, but I wanted to install linux port of your library, but I think, the repository does not work correctly. I get such following error:

    W: Failed to fetch http://tech.unige.ch/packages/dists/quantal/main/source/Sources 404 Not Found
    W: Failed to fetch http://tech.unige.ch/packages/dists/quantal/main/binary-amd64/Packages 404 Not Found
    W: Failed to fetch http://tech.unige.ch/packages/dists/quantal/main/binary-i386/Packages 404 Not Found

    Thank you in advance for help
    Dariusz

  65. Posted February 27, 2013 at 12:48 am | #

    Some time ago I commented that I had successfully used mpfr::mpreal with std::complex for my fractal software, Saturn & Titan. Development of this software is done on Linux with g++ and recently with clang++, the software when nearing release is also built on Windows 7 using Microsoft’s compiler, using mingw64 and g++ is possible but the resulting programs are slow compared with the native build using Visual Studio 2010 Express.

    You did warn me that the Microsoft implementation of std::complex was problematic and indeed you are right, it just doesn’t like std::complex<mpfr::mpreal>, I made some progress with specialisation until I came across a compilation problem with division of std::complex<mpfr::mpreal> numbers at which point I abandoned the use of std::complex<mpfr::mpreal>.

    The quickest method of producing a complex number class that used mpfr::mpreal was to take the GNU std::complex library and convert it into the mpfr::mpcomplex class, I’ll change the mpfr namespace if you object. I’ve omitted the code for handling << and >> stream operators.

    I can send you the resulting mpcomplex.h and mpcomplex.cc if you would like to add complex number support to MPFR C++.

  66. Posted February 27, 2013 at 10:04 pm | #

    I’m now testing my source package on various distributions of Linux. For Ubuntu 10.04, it has MPFR 2.4.2 and GMP 4.3.2. The library versions are greater than those stated as being minimum requirements for MPFR C++.

    The build fails because MPFR_RNDN is not declared in MPFR 2.4.2 so the minimum requirements needs to be revised.

  67. A.F
    Posted April 21, 2013 at 12:42 pm | #

    I tried using Eigen with mpreal but I hit a little snag along the way. I followed the instructions given by the Eigen website which makes use of the mprealsupport file but when I ran the sample code I get the following message:

    mpreal_max is not a member of mpfr

    This error comes from the lowest and highest functions defined in the MPRealSupport file. I tried to use the mpreal_max function with the mpreal.h header file
    and I get a similar error – it appears that this function doesn’t exist. If I get rid of this function in the MPRealSupport file then the sample code provided by Eigen runs without problem.

    Any thoughts on this?

    thanks

    • RP
      Posted June 22, 2014 at 4:22 am | #

      I looked at the Eigen2 version replace the mpreal_max with the function the maxval found in Eigen2.

  68. Terry Lyons
    Posted April 22, 2013 at 1:36 am | #

    Hi, I am trying to set up mpreal – in boost. I am running VS2012 with update2, and Boost 1.53.0; unfortunately the compile is full of errors e.g. I get ambiguous functions as my first errors when I run the code of Tsai (Posted May 31, 2011 at 6:32 pm) above. I have not modified mpreal.hpp. I can get examples that use mpreal directly to work with no trouble. I would appreciate suggestions? (I have compiled it with the 2010 and 2012 toolsets with same errors). Overall it seems a great tool.

    1>R:\sdks\boost\boost_1_53_0\boost/math/bindings/mpreal.hpp(299): error C2593: ‘operator *’ is ambiguous
    1> R:\sdks\boost\boost_1_53_0\boost/math/bindings/mpreal.hpp(47): could be ‘mpfr::mpreal mpfr::operator *(const mpfr::mpreal &,const T &)’ [found using argument-dependent lookup]
    1> with
    1> [
    1> T=int
    1> ]
    1> R:\sdks\mpfr_mpir\mpfr_mpir_x86_x64_msvc2010\current\mpfrcpp\mpreal.h(734): or ‘const mpfr::internal::result_type::type mpfr::operator *(const mpfr::mpreal &,const Rhs &)’ [found using argument-dependent lookup]
    1> with
    1> [
    1> Rhs=int
    1> ]
    1> while trying to match the argument list ‘(mpfr::mpreal, int)’

  69. Smjee
    Posted May 5, 2013 at 9:18 am | #

    I have used the MPFR library earlier. I must say that this C++ implementation is much easier to use. I am wondering how you change the rounding mode (I believe the default is RNDN) from the C++ wrapper. For example in MPFR, we could choose the rounding mode during every operation (like add, sqrt etc). But how do I set the rounding mode to RNDZ for example in C++ wrappers?

  70. Thomas Culbertson
    Posted May 28, 2013 at 1:08 am | #

    Hi Pavel,

    Just starting to use your wrapper, great stuff. Saved me some headaches over mpfr_t in my recursive decent parser. I had an issue with your toString() method however… it seems that the following code lines 1652-1664 uses a different method of string casting for newer versions of mpfr which ignores the base parameter:

    //#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
    //
    // // Use MPFR native function for output
    // char format[128];
    // int digits;
    //
    // digits = n > 0 ? n : bits2digits(mpfr_get_prec(mp));
    //
    // sprintf_s(format,”%%.%dRNg”,digits); // Default format
    //
    // return toString(std::string(format));
    //
    //#else

    Can you comment on why this is (or if I am just misunderstanding something)?

    Thanks in advance.

  71. Dirich
    Posted July 8, 2013 at 6:09 pm | #

    Hello Pavel, I am reporting an error I encountered in reading formatted inputs when switching type from double to mpreal.
    Specifically, if there is a comma after a number instead of a space, the c_str() call in “inline std::istream& operator>>(std::istream &is, mpreal& v)” causes an “Assertion Failed” runtime error.
    A program demostrating the problem can be found in the first post at http://ubuntuforums.org/showthread.php?t=2160022
    Nothing major, of course, but I think it is worth reporting since the change of type causes unexpected errors in an otherwise working code.
    Thanks for the awesome wrapper!

    • Posted July 17, 2013 at 9:30 pm | #

      Hello Dirich,

      Thank you for the information – I will make necessary changes in revision.

  72. Jim Calabrese
    Posted July 16, 2013 at 3:01 am | #

    I am having trouble getting mpreal to compile using vc++ 2005. Are there step by step instructions somewhere? Here is what I tried:
    1. downloaded the zips suggested on this page
    2. added the folders to my include directories listing
    3. in code, used #include “mpreal.h”
    4. used the following code:
    using mpfr::mpreal;
    mpreal number;
    number = “5”;
    5. Got the following error:
    error LNK2019: unresolved external symbol _mpfr_get_default_rounding_mode referenced in function “public: static enum mpfr_rnd_t __cdecl mpfr::mpreal::get_default_rnd(void)” (?get_default_rnd@mpreal@mpfr@@SA?AW4mpfr_rnd_t@@XZ)

    i know i’m doing something wrong, but i can’t figure out what it is

    • Posted July 17, 2013 at 9:28 pm | #

      You have to install MPFR & MPIR libraries as well – see above on this page, it has the information and download links.

      • Justin
        Posted October 31, 2013 at 1:53 am | #

        I installed MPFR ,GMP and MPIR libraries, when I compile like this : g++ -o example example.cpp -lmpfr -lgmp, still get error :

        mpreal.h: In function ‘int mpfr::sgn(const mpfr::mpreal&)’:
        mpreal.h:1854: error: ‘mpfr_signbit’ was not declared in this scope
        mpreal.h: In member function ‘mpfr::mpreal& mpfr::mpreal::setSign(int, mpfr_rnd_t)’:
        mpreal.h:1860: error: ‘mpfr_setsign’ was not declared in this scope
        mpreal.h: In function ‘const mpfr::mpreal mpfr::besselj0(const mpfr::mpreal&, mpfr_rnd_t)’:
        mpreal.h:2159: error: ‘mpfr_j0’ was not declared in this scope
        mpreal.h: In function ‘const mpfr::mpreal mpfr::besselj1(const mpfr::mpreal&, mpfr_rnd_t)’:
        mpreal.h:2160: error: ‘mpfr_j1’ was not declared in this scope
        mpreal.h: In function ‘const mpfr::mpreal mpfr::bessely0(const mpfr::mpreal&, mpfr_rnd_t)’:
        mpreal.h:2161: error: ‘mpfr_y0’ was not declared in this scope
        mpreal.h: In function ‘const mpfr::mpreal mpfr::bessely1(const mpfr::mpreal&, mpfr_rnd_t)’:
        mpreal.h:2162: error: ‘mpfr_y1’ was not declared in this scope
        mpreal.h: In function ‘const mpfr::mpreal mpfr::remainder(const mpfr::mpreal&, const mpfr::mpreal&, mpfr_rnd_t)’:
        mpreal.h:2181: error: ‘mpfr_remainder’ was not declared in this scope
        mpreal.h: In function ‘const mpfr::mpreal mpfr::remquo(long int*, const mpfr::mpreal&, const mpfr::mpreal&, mpfr_rnd_t)’:
        mpreal.h:2188: error: ‘mpfr_remquo’ was not declared in this scope
        mpreal.h: In function ‘const mpfr::mpreal mpfr::lgamma(const mpfr::mpreal&, int*, mpfr_rnd_t)’:
        mpreal.h:2205: error: ‘mpfr_lgamma’ was not declared in this scope
        mpreal.h:2206: error: ‘mpfr_lgamma’ was not declared in this scope
        mpreal.h: In function ‘const mpfr::mpreal mpfr::besseljn(long int, const mpfr::mpreal&, mpfr_rnd_t)’:
        mpreal.h:2215: error: ‘mpfr_jn’ was not declared in this scope
        mpreal.h: In function ‘const mpfr::mpreal mpfr::besselyn(long int, const mpfr::mpreal&, mpfr_rnd_t)’:
        mpreal.h:2222: error: ‘mpfr_yn’ was not declared in this scope
        mpreal.h: In function ‘const mpfr::mpreal mpfr::fms(const mpfr::mpreal&, const mpfr::mpreal&, const mpfr::mpreal&, mpfr_rnd_t)’:
        mpreal.h:2252: error: ‘mpfr_fms’ was not declared in this scop

        #include
        #include “mpreal.h”

        using namespace mpfr;
        using namespace std;

        mpreal N011(mpreal VA1, mpreal VA2)
        {
        mpreal N01;
        N01 = sqrt(-2*log(1-VA1))*cos(2*const_pi()*VA2);
        return N01;
        }

        int main()
        {
        mpreal::set_default_prec(1024);

        cout.precision(50);
        cout << N011(0.2, 0.3) << endl;

        return 0;
        }

        I really want to use mpfr c++ with Eigen, can anybody help me figure out how to solve this problem?

        • Posted October 31, 2013 at 2:17 am | #

          What version of MPFR do you use? It seems to be too old.

          • Justin
            Posted October 31, 2013 at 3:20 am | #

            it works now , I forgot the dynamic linking.

          • Justin
            Posted October 31, 2013 at 3:33 am | #

            Thanks, ! but how do I combine mpfr c++ and Eigen ? I got the below error by compiling: g++ -o test_test -L/home1/02084/zzwtgts/lib -I/home1/02084/zzwtgts/include test_test.cpp -lmpfr -lgmp ,I downloaded MPRealSupport and put it in my Eigen directory , anything wrong?

            test_test.cpp

            #include
            #include
            #include
            using namespace mpfr;
            using namespace Eigen;
            int main()
            {
            // set precision to 256 bits (double has only 53 bits)
            mpreal::set_default_prec(256);
            // Declare matrix and vector types with multi-precision scalar type
            typedef Matrix MatrixXmp;
            typedef Matrix VectorXmp;
            MatrixXmp A = MatrixXmp::Random(100,100);
            VectorXmp b = VectorXmp::Random(100);
            // Solve Ax=b using LU
            VectorXmp x = A.lu().solve(b);
            std::cout << "relative error: " << (A*x – b).norm() / b.norm() << std::endl;
            return 0;
            }

            ~
            ~
            In file included from test_test.cpp:2:
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:33:20: error: mpreal.h: No such file or directory
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:114:38: error: missing binary operator before token "("
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:80: error: ‘mpfr’ was not declared in this scope
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:80: error: template argument 1 is invalid
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:81: error: ‘mpfr’ was not declared in this scope
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:81: error: template argument 1 is invalid
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:112: error: ‘mpfr’ has not been declared
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:112: error: expected constructor, destructor, or type conversion before ‘random’
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:131: error: ‘mpfr’ has not been declared
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:131: error: expected constructor, destructor, or type conversion before ‘random’
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:136: error: expected ‘,’ or ‘…’ before ‘::’ token
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:136: error: ISO C++ forbids declaration of ‘mpfr’ with no type
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport: In function ‘bool Eigen::internal::isMuchSmallerThan(int)’:
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:138: error: ‘mpfr’ is not a class or namespace
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:138: error: ‘a’ was not declared in this scope
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:138: error: ‘mpfr’ is not a class or namespace
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:138: error: ‘b’ was not declared in this scope
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:138: error: ‘prec’ was not declared in this scope
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport: At global scope:
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:141: error: expected ‘,’ or ‘…’ before ‘::’ token
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:141: error: ISO C++ forbids declaration of ‘mpfr’ with no type
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport: In function ‘bool Eigen::internal::isApprox(int)’:
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘mpfr’ is not a class or namespace
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘a’ was not declared in this scope
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘b’ was not declared in this scope
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘mpfr’ is not a class or namespace
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘mpfr’ is not a class or namespace
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘mpfr’ is not a class or namespace
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘prec’ was not declared in this scope
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport: At global scope:
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:146: error: expected ‘,’ or ‘…’ before ‘::’ token
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:146: error: ISO C++ forbids declaration of ‘mpfr’ with no type
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport: In function ‘bool Eigen::internal::isApproxOrLessThan(int)’:
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:148: error: ‘a’ was not declared in this scope
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:148: error: ‘b’ was not declared in this scope
            /home1/02084/zzwtgts/include/Eigen/MPRealSupport:148: error: ‘prec’ was not declared in this scope
            test_test.cpp: At global scope:
            test_test.cpp:4: error: ‘mpfr’ is not a namespace-name
            test_test.cpp:4: error: expected namespace-name before ‘;’ token
            test_test.cpp: In function ‘int main()’:
            test_test.cpp:9: error: ‘mpreal’ has not been declared
            test_test.cpp:11: error: ‘mpreal’ was not declared in this scope
            test_test.cpp:11: error: template argument 1 is invalid
            test_test.cpp:11: error: invalid type in declaration before ‘;’ token
            test_test.cpp:12: error: ‘mpreal’ cannot appear in a constant-expression
            test_test.cpp:12: error: template argument 1 is invalid
            test_test.cpp:12: error: invalid type in declaration before ‘;’ token
            test_test.cpp:13: error: ‘MatrixXmp’ is not a class or namespace
            test_test.cpp:14: error: ‘VectorXmp’ is not a class or namespace
            test_test.cpp:16: error: request for member ‘lu’ in ‘A’, which is of non-class type ‘main::MatrixXmp’
            test_test.cpp:17: error: request for member ‘norm’ in ‘((A * x) – b)’, which is of non-class type ‘int’
            test_test.cpp:17: error: request for member ‘norm’ in ‘b’, which is of non-class type ‘main::VectorXmp’

          • Justin
            Posted October 31, 2013 at 3:49 am | #

            mpfr-3.1.2, the latest version

  73. Posted October 30, 2013 at 8:26 pm | #

    dear,
    can I/we have a c++ header for multiprecision integers only.I have tried the real version ,..it works with my c++ routines for clipping(only 50X slow down).I want to try out a integer only library available on the net which has its own 64 bit integer manipulation routines.
    I expect it as easy to use as mpreal….just substitute double by mpreal and the program compiled without further effort.
    Mahesh Naik

    • Posted October 30, 2013 at 8:29 pm | #

      Modern systems/compilers have built-in 64-bit integers. If you want more digits – take a look on MPIR/GMP.

    • Jirka Hladky
      Posted October 30, 2013 at 11:10 pm | #

      You might also want to check the 128-bit integer type built into the GCC. Google __uint128_t

  74. Justin
    Posted November 1, 2013 at 4:54 am | #

    Dear Pavel:

    You mentioned that user can equip Eigen with arbitrary precision arithmetic by:

    1. Installing MPFR and GMP libraries.
    2. Using MPFR C++ interface (mpreal.h, mpreal.cpp) along with header file mpreal_eigen.h
    3. Using mpreal type (provided by MPFR C++) instead of built-in type double or float.

    But I also found head file #include in this module

    http://eigen.tuxfamily.org/dox/unsupported/group__MPRealSupport__Module.html

    My questions is which head file is better ? mpreal_eigen.h or Eigen/MPRealSupport?

    I tried mpreal_eigen.h with mpreal.h, but still get error :

    In file included from test_test.cpp:3:
    mpreal_eigen.h:51: error: expected unqualified-id before ‘<’ token
    mpreal_eigen.h:56: error: expected ‘;’ before ‘inline’
    mpreal_eigen.h:61: error: expected unqualified-id before ‘<’ token
    test_test.cpp:15: error: expected ‘;’ at end of input
    test_test.cpp:15: error: expected ‘}’ at end of input

    my test_tes.cpp file is very simple:

    #include
    #include “mpreal.h”
    #include “mpreal_eigen.h”

    using namespace mpfr;
    using namespace Eigen;

    int main()
    {
    mpreal::set_default_prec(256);
    typedef Matrix MatrixXmp;
    MatrixXmp A = MatrixXmp::Random(100,100);
    std::cout << "relative error: " << A << std::endl;
    return 0;
    }

    Could you please give me some suggestions on how to resolve this problem? Thanks!

    • Posted November 7, 2013 at 10:55 am | #

      Dear Justin,

      Do not use mpreal_eigen.h. It is obsolete and no longer supported.

      Please use #include <unsupported/Eigen/MPRealSupport> as described above on the page.

  75. Posted November 10, 2013 at 9:43 pm | #

    I am quite new to both mpfr and mpreal, so maybe I just haven’t read the manual thoroughly enough ..

    I am transmitting mpreals over a network, and I want to do this with as little conversion as possible. As I want to be independent of 32/64 bit issues (and also for other reasons) I am not trying to access the raw internals, but mpfr_set/get_str instead.

    This sort of works, but the precision is less than that of long doubles:

    #define get_mandel_value(dst,src) { FLOAT_TYPE dst_tmp(src.val); dst = dst_tmp; }
    #define set_mandel_value(dst,src) strncpy(dst.val,src.toString("%.128RNe").c_str(),mpfr_buff_size - 16)

    (the buff_size – 16 is a leftover, when doing mpfr_get/set_str, the buffer need some extra space for sign etc.).

    I would like to do something like this:

    #define get_mandel_value(dst,src) \
    { \
    if ( mpfr_set_str(dst.mpfr_ptr(),src.val,mpfr_str_base,MPFR_RNDN ) == -1 ) { printf("get_mandel_value failed!\n"); exit(1); } \
    }

    #define set_mandel_value(dst,src) \
    { \
    mpfr_exp_t *expptr = new mpfr_exp_t(); \
    memset(dst.val,0,mpfr_buff_size); \
    if ( mpfr_get_str(dst.val,expptr,mpfr_str_base,mpfr_buff_size-16,src.mpfr_ptr(),MPFR_RNDN) == NULL ) { printf("set_mandel_value failed!\n"); exit(1); }\
    delete expptr; \
    }

    As you can see, I am calculating Mandelbrot 🙂 I have a FLOAT_TYPE which can be either a long double or a mpreal float.
    Also, I am a bit confused over the expptr, why is it necessary.

    I have tried different format strings – maybe I didn’t hit the correct combination?
    I have used mpfr_set_default_prec(1024) and even 8192 – no change.

    What is the best (precise) way of marshalling mpreals?

    Btw: Thanks for a great library – saved me tons of work 🙂

    • Posted November 10, 2013 at 11:29 pm | #

      Update1 : It seems, that I hit the precision of the “double” data type.
      Somewhere along the way it is converted to a double.
      Update2 : I have also tried dst = src.val in the first version of get_mandel_value, so no temporary variable is needed. No change in precision, however.

      • Posted November 11, 2013 at 2:56 am | #

        Update3: The precision loss was because I had forgot to set default precision in ALL the threads 🙂

        The question still remains: What is the most precise way of transmitting mpreals over a network?

        • Posted November 11, 2013 at 2:39 pm | #

          Using the strings is the official way.

          If it is too slow (lots of numbers needs to be transferred) – you need to access the internals of mpfr_t.

          Btw, you don’t need to allocate expptr in heap every time. Just define expptr as variable and pass &expptr to mpfr_get_str.
          Stack allocations are much faster then heap.

          • Posted November 12, 2013 at 4:06 am | #

            Thank you for the reply. Everything works now, I read the manual some more (and also the mpreal.h include file).

            I am calculating Mandelbrot (don’t ask why) using any available CPU resource on the network. So I need to send a set of coordinates to any machine (32 or 64 bit), and the bottleneck is CPU time, not the network, so I can live with long strings.

            I looked in mpreal.h and found, that I didn’t need to access any mpfr internals directly. I can use the mpreal functions, which beautifully wrap up all the mpfr internals for me 🙂 The mpreal internals stores bits in limbs, which most likely are 32/64 bit dependent, so I can’t use any access to them – I need it in a normalized format, and it seems that strings are the only good way to do that.

            I want to be able to switch between normal long double floating point numbers and mpreals – and it is easily done, all that is needed is a way of transporting the numbers using the S_MANDEL_FLOAT structure.

            I was audacios enough to make some timings on a zoom somewhere in the Mandelbrot image:

            // single threaded @ 1.2 GHz:
            //   SD -> 233M (double)
            //   LD -> 220M (long double)
            //   64 -> 758K (mpfr with 64 bits)
            //  256 -> 672K
            //  512 -> 544K
            // 1024 -> 340K
            // 2048 -> 202K
            // 4096 -> 94K

            That is, a 2048 bit mpreal is approximately 1000 times slower than a long double, but a 256 bit mpreal is more than 3 times faster than a 2048 mpreal. I know that it is impossible to make proper floating point benchmarks, because computing time depends on the input number(s), so other people may get other results when testing.

            I ended up with the following header file (note that mpfr_buff_size may be too large, but when experimenting with very large number of bits, then it can easily get too small):

            #include "mpreal.h"
            using mpfr::mpreal;

            #define FAST 1
            #define FLOAT_PREC 256

            #if FAST == 0

            #define mpfr_buff_size 16384
            #define mpfr_str_base 10

            #pragma pack(push,1)
            typedef struct
            {
                char val[mpfr_buff_size];
            } S_MANDEL_FLOAT;

            #pragma pack(pop)

            #define FLOAT_TYPE mpreal
            #define F2LD(val) val.toLDouble()

            #define get_mandel_value(dst,src) dst = src.val;
            #define set_mandel_value(dst,src) \
                strncpy(dst.val,src.toString(0,mpfr_str_base,MPFR_RNDN).c_str(),mpfr_buff_size - 16);

            #else

            #define FLOAT_TYPE long double
            #define F2LD(val) (long double)val

            #pragma pack(push,1)
            typedef struct
            {
                FLOAT_TYPE value;
            } S_MANDEL_FLOAT;

            #pragma pack(pop)

            #define get_mandel_value(dst,src) dst = src.value
            #define set_mandel_value(dst,src) dst.value = src

            #endif

          • Posted November 12, 2013 at 6:32 pm | #

            Comparison and code looks good.

            To make things shorter you might use simplified version with default parameters: src.toString().c_str().

            ***
            I have routines for mpreal serialization to bitstream (to avoid string conversion) based on mpfr_t internal raw buffers.

            However it suffers from being dependent on limb size and it is based on undocumented MPFR features subject to change anytime.

            Inclusion of universal serializers into MPFR itself has been discussed for years among developers. You might find some draft routines in trunk branch in SVN. However it is not critical for your application as I see.
            ***

            Anyway, thank you for your work and please keep me updated on your experience with mpreal.

  76. Nikos
    Posted November 17, 2013 at 9:58 pm | #

    Dear Pavel,

    thank you for sharing your code with us.

    I have to use the exponential function with a negative argument. It seems that the identity

    \exp(x)= \sinh(x)+\sqrt{1+\sinh^2(x)},

    although mathematically correct, it has numerical evaluation problems when x<0. For example please try: cout << exp( float_precision(-1.7E2) ) << endl;

    The result is incorrect.

    Using the standard c math library, the results is correct, i.e., cout << exp( -1.7E2 ) <<endl;.

    I would much appreciate if you check the problem and let me know how the above problem can be corrected.

    Thanks and best regards,
    Nikos

    • Posted November 17, 2013 at 11:03 pm | #

      I see no such problem:

      /* use 30 digits precision */
      int digits = mpfr::digits2bits(30);
      mpfr::mpreal::set_default_prec(digits);

      mpfr::mpreal x("-1.7e2");

      std::cout.precision(20);

      std::cout << exp(x) << std::endl; std::cout << exp(x.toDouble()) << std::endl;

      Output:

      1.4788975056432133844e-74 <-- mpreal 1.4788975056432133e-074

      • Nikos
        Posted November 17, 2013 at 11:38 pm | #

        Thank you for your prompt response!

        I am using Visual Studio C++ 2010 binaries for MPFR 3.0.1 and MPIR 2.3.0 given as a zip file in the “Download” section of the current page. So, I only use in my VS2010 project the 4 header and 1 cpp files provided therein. The header I use in my project to conduct floating-point calculations is: #include “fprecision.h”. Thus, I cannot compile your code.

        Are there any equivalent commands for my case to adjust the accuracy according to your previous post? Or, do I have to include some more libraries?

        Thanks once again,
        Nikos

        • Posted November 18, 2013 at 12:01 am | #

          I have no idea what is “fprecision.h”.

          You need to include only one file – “mpreal.h” (and install mpfr/mpir as you did already).

  77. Nikos
    Posted November 18, 2013 at 1:40 am | #

    Dear Pavel,

    thank you so much for your help!

    Following your suggestions I managed to correctly evaluate the exponential function with any negative argument.

    Best,
    Nikos

    PS: The header “fprecision.h” mentioned above has nothing to do with the MPFR project. Sorry for any misunderstanding caused.

  78. Nikos
    Posted November 18, 2013 at 3:09 am | #

    One final question.

    How is it possible to change the number of bits that is used to perform floating-point arithmetic?

    I tried your above lines

    /* use 30 digits precision */
    int digits = mpfr::digits2bits(30);
    mpfr::mpreal::set_default_prec(digits);

    mpfr::mpreal x("-1.7e2");

    cout<< sizeof(x) << endl;

    Using any number instead of 30, the sizeof function always returns 24 as the output. So, I cannot change the mpfr::mpreal numbers accuracy.

    Can you please give some advise?

    Thanks,
    Nikos

    • Posted November 18, 2013 at 11:35 am | #

      Size of “mpreal” has no relation to precision.
      Number is stored in heap memory, “mpreal” has only pointers to its data – that is why sizeof(mpreal) is always the same.

      Use machine epsilon to check the actual accuracy of a precision / number:

      std::cout << mpfr::machine_epsilon(128) << std::endl; std::cout << mpfr::machine_epsilon(x) << std::endl;

      Use getPrecision()/setPrecision() to get the precision of a number.

  79. Florian
    Posted December 25, 2013 at 12:15 am | #

    Dear Pavel,
    first of all, I would like to say that MPFR is a great library and helps me a lot. I am not the biggest expert in using MPFR so I do not know what this error means:

    sub1sp.c:658: assertion failed: bbcp != (mp_limb_t) -1

    I appears in the middle of a big loop where many very small values are computed and used.

    Can you please give some advise?

    Have a nice Christmas!

    Thank you very much!
    Florian

  80. Florian
    Posted December 27, 2013 at 11:55 pm | #

    Dear Pavel,
    first of all, thank you for your work and your package.
    I have a question about an error I get when I am running a program using MPFR:

    sub1sp.c:658: assertion failed: bbcp != (mp_limb_t) -1

    The program uses and computes a lot of very small values.

    Could you help me, please?

    Thank you,
    Florian

  81. Florian
    Posted December 27, 2013 at 11:55 pm | #

    Sorry for the double posting before

  82. Posted February 7, 2014 at 6:17 am | #

    Recently I installed the ‘Ubuntu package for MPFR C++’ an my aged laptop computer and was completely surprised that replacing type double by mpreal caused no noticible increase in computation time for precisions till incredible 256 decimal digits. Similar tests two years ago saw computations slowed down by a factor of ~100. Unbelievable progress, congratulations !!!!

    • Posted February 8, 2014 at 3:50 pm | #

      Thank you very much for your comment!

      Indeed performance has been the main priority all this time. Many knowledgeable people contributed to the code (e.g. RVO), and technology moved further (e.g. move semantic). All combined gave significant boost for the speed.

      I don’t know what version of MPFR/GMP you are using, but improvements there might contribute the most to the performance ;).

  83. Posted February 18, 2014 at 12:25 am | #

    Just to correct my previous premature and over-optimistic note. The observation about slowing down by a factor ~100 was from 2009 and thus not only two years ago. The observation that using mpreal instead of double did not increase computation time noticibly was brought about by a program that was very special in being graphical to a high degree. Graphics-related floating point computations are done in my C+- system always in double so that mpreal was involved only in a small part of the computation. For a less-graphical, ‘normal’ program I got: The factor by which prec n is slower than double was found to be 2.36 2.50 3.40 for n = 64, 128, 256 respectively. Also this is admirable progress and the congratulations need not be withdrawn in any way.

  84. david edwards jr
    Posted April 23, 2014 at 11:21 pm | #

    I get the following error;
    1>c:\davids\vcnet\mpfrc++-3.5.6\mpreal.h(2566): error C2665: ‘mpfr::grandom’ : none of the 2 overloads could convert all the argument types
    from the code:
    #if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))
    inline const mpreal grandom(unsigned int seed = 0)
    {
    static gmp_randstate_t state;
    static bool isFirstTime = true;

    if(isFirstTime)
    {
    gmp_randinit_default(state);
    gmp_randseed_ui(state,0);
    isFirstTime = false;
    }

    if(seed != 0) gmp_randseed_ui(state,seed);

    return mpfr::grandom(state);
    }
    #endif

    I am using visual studio 2013 and downloaded the files yesterday from your website
    I have also had to comment out:
    #define MPREAL_HAVE_INT64_SUPPORT

    thank you

    david

  85. Jorge
    Posted May 8, 2014 at 6:06 pm | #

    Hi. I found your library very nice. I had written one but yours is much superior. Thanks for sharing it with the world.

    I have a ticket to this code: when compiling with g++ -Wall -Wextra -Wfatal-errors, I get the warning:

    mpreal.h:2402:102: warning: unused parameter 'r' [-Wunused-parameter]

    My understanding is that this is because the function

    inline const mpreal const_infinity (int sign = 1, mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd())

    is not using its last parameter, r.

    Thus, it could have be re-written into

    inline const mpreal const_infinity (int sign = 1, mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t)

    if we want to keep backward compatibility and library systematic input of rounding parameter, or to

    inline const mpreal const_infinity (int sign = 1, mp_prec_t p = mpreal::get_default_prec())

    if we allow backward incompatibility.

    Regards,
    Jorge

    • Posted May 8, 2014 at 7:33 pm | #

      Hi Jorge. Thank you for your feedback.

      I think it is better to just remove unused parameter. Compatibility will be preserved, since nobody was using the ‘r’ anyway :).

      Will update repository shortly.

  86. Zhoulai
    Posted June 3, 2014 at 3:53 am | #

    Hi, Pavel,

    Thank you very much for your library! I like it.

    Do you know if we can pass a function pointer of type mpreal->mpreal to Boost’s optimization function templates, say, of this interface:

    template class F, class T
    std::pair T, T brent_find_minima(F f, T min, T max, int bits, boost::uintmax_t& max_iter) ?

    I got this compilation error: “reference to overloaded function could not be resolved” when calling

    boost::math::tools:: brent_find_minima(p_implm, begin, end, bits, iter);

    in which p_implm is a user-defined simple function of type mpreal->mpreal.

    The compilation error is in the screenshot
    https://www.evernote.com/shard/s306/sh/e357903e-245c-4c7b-851f-86c331bc04f1/253e2ecbb100465d560a6c53183073d3

    Note that the error points to policy.hpp of boost library. So I guess I made something wrong or maybe
    mpreal is not designed to work the way as I naively thought.

    What do you think?

    • Posted June 3, 2014 at 11:18 am | #

      Hi Zhoulai,

      The problem there is that constant “std::numeric_limits::digits” is undefined for “mpreal”.
      Since “mpreal” can have variable number of digits (that is the point of the library) – “digits” is defined as function for the “mpreal”.

      Please check the std::numericl_limits<mpreal> specialization at the end of mpreal.h.

      The possible solution would be to add constant “std::numeric_limits<mpreal>::digits” with some dummy value – just so that boost would not complain anymore.

      • Zhoulai
        Posted June 3, 2014 at 11:43 am | #

        Thank you for your clarification. Do you mean that I need to manually modify mpreal.h?

        • Posted June 3, 2014 at 12:32 pm | #

          In a few minutes I will release the updated version with special workaround for the problem.

          Basically you will need to disable one macro in mpreal.h in order to have full compatibility with standard numeric_limits.

          • Posted June 3, 2014 at 12:49 pm | #

            It is already updated. See here:
            https://bitbucket.org/advanpix/mpreal/

            1. Comment out the following line:

            #define MPREAL_HAVE_DYNAMIC_STD_NUMERIC_LIMITS

            2. Do the proper modifications for “digits”, etc. at the end of mpreal.h file – so that it matches your precision.

  87. Jorge
    Posted June 10, 2014 at 9:00 pm | #

    Hi Pavel.

    Two other minor issues that the compiler warns:

    line 2977 (of trunk)

    inline static int digits() { return mpfr::mpreal::get_default_prec(); }

    should read

    inline static int digits() { return (int)mpfr::mpreal::get_default_prec(); }

    Line 1883-1886

    inline int mpreal::getPrecision() const
    {
    return mpfr_get_prec(mp);
    }

    should read

    inline int mpreal::getPrecision() const
    {
    return (int)mpfr_get_prec(mp);
    }

    both of them are warnings about implicit conversion precision lost.

    Regards,
    Jorge

    • Posted June 12, 2014 at 10:54 pm | #

      Hi Jorge,

      Thank you for your report. All warnings have been fixed along with other improvements released today. Please check the new version.

  88. Rodney James
    Posted August 22, 2014 at 9:34 pm | #

    Hi Pavel,

    I have been having trouble using mpfr::mpreal with the latest LLVM (clang++) compiler on Mac OS. It seems to come up when using std::complex and performing complex arithmetic — the compiler is generating C++11 copysign functions internally, which then generate errors like:


    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/complex:632:23: error:
    no matching function for call to ‘copysign’
    __d = copysign(_Tp(0), __d);
    ^~~~~~~~
    /usr/include/math.h:526:15: note: candidate function not viable: no known conversion from
    ‘mpfr::mpreal’ to ‘double’ for 1st argument
    extern double copysign(double, double);
    ^

    This used to work fine on earlier versions of clang++, and it works with other compilers. Any ideas on how to get this to work?

    Thanks,

    Rodney

    • Posted August 22, 2014 at 10:00 pm | #

      Hi Rodney,

      The simplest way would be to overload “copysign” function with your own version capable of working with “mpreal”.

      The standard implementations of std::complex are usually hardwired to “double” precision very much (especially math. functions).
      Please be careful and check std::complex you are using.

      • Rodney James
        Posted August 22, 2014 at 10:48 pm | #

        Hi Pavel,

        I found a copysign function in MPFR, and I added the following to mpreal.h (and the appropriate friend statement) and everything seems to work fine now.


        inline const mpreal copysign (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())
        {
        mpreal a;
        mp_prec_t yp, xp;

        yp = y.get_prec();
        xp = x.get_prec();

        a.set_prec(yp>xp?yp:xp);

        mpfr_copysign(a.mp, x.mp, y.mp, rnd_mode);

        return a;
        }

        Thanks,

        Rodney

        • Posted August 22, 2014 at 10:56 pm | #

          Great! Thank you.

          Will add this function to mpreal.h.

          • daniel brake
            Posted March 17, 2015 at 3:01 am | #

            I wish to reiterate the caution against using std::complex with any types other than float, double, and long double. conversions to double WILL happen, and you will get crazy accuracy loss.

          • Posted March 17, 2015 at 12:19 pm | #

            Daniel,

            You are right, in general it is not a good idea to use std::complex<mpfr::mpreal> without detailed checks.

            But actually this depends on std::complex implementation.
            For instance, GCC seems to behave well: http://goo.gl/i6zHQB

            Whereas MSVC provides std::complex hardwired to standard types.

  89. Gordon
    Posted December 6, 2014 at 3:58 pm | #

    Hi, Pavel

    I’m trying to use MPRealSupport with Eigen 3.2.2 on Mac OS X 10.9. I followed the instructions on http://eigen.tuxfamily.org/dox/unsupported/group__MPRealSupport__Module.html

    build my code with -lgmp -lmpfr. Everything looks good until I run into EXC_I386_GPFLT error on first call to mpfr_set_d (assign a double value to a mpreal variable)

    my mpreal is 3.6.1, mpfr is 3.1.2-p10 and gmp is 6.0.0a. Do you have any idea on the problem? What’s the compatible version of mpreal, mpfr and gmp to work with mpreal support module in Eigen 3.2.2?

    Thanks
    Gordon

    • Gordon
      Posted December 7, 2014 at 8:44 am | #

      I found it’s my problem. I converted old code from c to c++ and failed to see a mpreal variable is uninitialized after malloc. Sorry for bothering you.

  90. Marco Pacini
    Posted March 19, 2015 at 10:13 pm | #

    Hi Pavel,

    first of all thank you very much for your library. I’d like you to note that using Xcode with Apple LLVM 6.0 compiler return the following warning:

    mpreal.h:306:60: warning: implicit conversion loses integer precision: ‘unsigned long’ to ‘unsigned int’ [-Wshorten-64-to-32]
    explicit operator int () const { return toULong(); }

    mpreal.h:309:60: warning: implicit conversion loses integer precision: 'unsigned long' to 'unsigned int' [-Wshorten-64-to-32]
    explicit operator unsigned () const { return toULong(); }

    P.S. I apologize for my bad english.

  91. Posted April 15, 2015 at 10:48 pm | #

    Hi,

    I’m getting an assertion on the following code:

    mpfr::mpreal::set_default_prec(64);
    mpfr::random(1);
    Float point = mpfr::random();
    assert(point == Float(point.toString()));

    This is serious to me because I’m using `toString` to serialise data points into a file (e.g. it is used by <= MPFR_VERSION_NUM(2,4,0)`, the function `bits2digits(mpfr_get_prec(mp))` may round off to below the number of digits required.

    A simple solution is to use `bits2digits(mpfr_get_prec(mp)) + 1`.

    I believe you can use the code above as a regression test.

    Thanks,
    Jorge

    • Posted April 16, 2015 at 1:00 pm | #

      Thank you Jorge for your report – this is now fixed (by adding the 1).
      Indeed mpfr_get_str() uses more sophisticated algorithm to determine the minimum required precision.

  92. Matteo
    Posted May 10, 2015 at 10:52 pm | #

    Hi,
    I just start using your c++ wrapper and it is very good.
    The problem that I have to face concern a very large summation (say 10000 terms). I am not sure how to answer to the questions:
    If each term in the summation has a precision of 20 digits, which is the precision of the final result?

    Thanks,
    Matteo

    • Posted May 11, 2015 at 11:09 am | #

      Take a look on the papers:

      Higham. The accuracy of floating point summation.
      Ogita, Rump, Oishi. Accurate sum and dot product.
      Demmel, Hida. Fast and accurate floating point summation with application to computational geometry.

      Summation algorithm from the last paper is implemented in MPFR C++, check the “sum” function. It guarantees full precision accuracy.

  93. Thomas
    Posted July 24, 2015 at 11:26 pm | #

    <algorithm> is missing for Visual Studio 2013 (probably other versions too), std::max isn’t recognized otherwise.

    Add at line 60:

    #ifdef _MSC_VER
        #include <algorithm>
    #endif

    • Posted July 24, 2015 at 11:32 pm | #

      You are absolutely correct. Thank you for reporting the issue!

    • Posted July 24, 2015 at 11:38 pm | #

      Committed the change to repository. Other compilers also need the header, not only MSVC :).

  94. Ax
    Posted August 5, 2015 at 1:46 am | #

    Hi!

    I’ve tried to include your wrapper class in my Visual Studio 2013 project, but when I try to compile it I get the following errors:

    mpreal.h(673): error C3861: ‘mpfr_set_uj’: identifier not found
    mpreal.h(681): error C3861: ‘mpfr_set_sj’: identifier not found
    mpreal.h(1001): error C3861: ‘mpfr_set_uj’: identifier not found
    mpreal.h(1001): error C3861: ‘mpfr_set_uj’: identifier not found
    mpreal.h(1727): error C3861: ‘mpfr_get_sj’: identifier not found
    mpreal.h(1728): error C3861: ‘mpfr_get_uj’: identifier not found
    mpreal.h(2395): error C2057: expected constant expression
    mpreal.h(2395): error C2466: cannot allocate an array of constant size 0
    mpreal.h(2395): error C2133: ‘p’ : unknown size

    For the first six errors I observe that I cannot find these functions, but there are functions such as mpfr_set_ui. Should I use these instead?

    For the last three erros (starting with error C2057) the code that doesn’t work is the following function:

    inline const mpreal sum(const mpreal tab[], const unsigned long int n, int& status, mp_rnd_t mode = mpreal::get_default_rnd())
    {
    mpfr_srcptr p[n];//<------- ERROR is here!

    for (unsigned long int i = 0; i < n; i++)
    p[i] = tab[i].mpfr_srcptr();

    mpreal x;
    status = mpfr_sum(x.mpfr_ptr(), (mpfr_ptr*)p, n, mode);
    return x;
    }

    Also, I used the Windows binaries for Visual Studio 2010 that you have linked to in your post. Should that cause any problems using VS2013?

    I’m quite clueless here – and not at all experienced in installing third-party libraries – so I would appreciate some help. It took me quite some time just to get the settings right so that Visual Studio would find the mpfr and mpir libraries at all.. :p

    • Posted August 5, 2015 at 12:14 pm | #

      Please use the latest version of the library from here: https://bitbucket.org/advanpix/mpreal/
      This will fix the second issue (C2057).

      As for non-found _*j functions – please use 64-bit build mode (x64).

      • Tomas Navratil
        Posted April 10, 2016 at 4:01 pm | #

        Hi Pavel, I am new in C++ programming. I have problem with compiling basic example in Visual Studio 2013.

        Example:

        #include
        #include
        #include
        #include

        int main(int argc, char* argv[])
        {
        using mpfr::mpreal;
        using std::cout;
        using std::endl;

        // Required precision of computations in decimal digits
        // Play with it to check different precisions
        const int digits = 50;

        // Setup default precision for all subsequent computations
        // MPFR accepts precision in bits – so we do the conversion
        mpreal::set_default_prec(mpfr::digits2bits(digits));

        // Compute all the vital characteristics of mpreal (in current precision)
        // Analogous to lamch from LAPACK
        const mpreal one = 1.0;
        const mpreal zero = 0.0;
        const mpreal eps = std::numeric_limits::epsilon();
        const int base = std::numeric_limits::radix;
        const mpreal prec = eps * base;
        const int bindigits = std::numeric_limits::digits(); // eqv. to mpfr::mpreal::get_default_prec();
        const mpreal rnd = std::numeric_limits::round_error();
        const mpreal maxval = std::numeric_limits::max();
        const mpreal minval = std::numeric_limits::min();
        const mpreal small = one / maxval;
        const mpreal sfmin = (small > minval) ? small * (one + eps) : minval;
        const mpreal round = std::numeric_limits::round_style();
        const int min_exp = std::numeric_limits::min_exponent;
        const mpreal underflow = std::numeric_limits::min();
        const int max_exp = std::numeric_limits::max_exponent;
        const mpreal overflow = std::numeric_limits::max();

        // Additionally compute pi with required accuracy – just for fun 🙂
        const mpreal pi = mpfr::const_pi();

        cout.precision(digits); // Show all the digits
        cout << "pi = " << pi << endl;
        cout << "eps = " << eps << endl;
        cout << "base = " << base << endl;
        cout << "prec = " << prec << endl;
        cout << "b.digits = " << bindigits << endl;
        cout << "rnd = " << rnd << endl;
        cout << "maxval = " << maxval << endl;
        cout << "minval = " << minval << endl;
        cout << "small = " << small << endl;
        cout << "sfmin = " << sfmin << endl;
        cout << "1/sfmin = " << 1 / sfmin << endl;
        cout << "round = " << round << endl;
        cout << "max_exp = " << max_exp << endl;
        cout << "min_exp = " << min_exp << endl;
        cout << "underflow = " << underflow << endl;
        cout << "overflow = " << overflow << endl;

        return 0;
        }

        When I tried to compile, there were these errors (It is similar problem as text above from AX):

        error C3861: 'mpfr_set_uj': identifier not found
        error C3861: 'mpfr_set_sj': identifier not found
        error C3861: 'mpfr_set_uj': identifier not found
        error C3861: 'mpfr_set_sj': identifier not found
        error C3861: 'mpfr_get_sj': identifier not found
        error C3861: 'mpfr_get_uj': identifier not found
        IntelliSense: identifier "mpfr_set_uj" is undefined
        IntelliSense: identifier "mpfr_set_sj" is undefined
        IntelliSense: identifier "mpfr_set_uj" is undefined
        IntelliSense: identifier "mpfr_set_sj" is undefined
        IntelliSense: identifier "mpfr_get_sj" is undefined
        IntelliSense: identifier "mpfr_get_uj" is undefined

        I tried compile 32 bit project with precompiled sources and 64 bit build mode, but nothing help me.

        I downloaded a pre built library from ,. Extract the zip, then I went to \mpir\dll\Win32\debug\. Here we have 3 files mpir.lib, mpir. pdb and a mpir.h. I copied the first 2 files mentioned above to C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\.
        I copied also mpfr.lib and mpfr.pdb from mpfr \dll\Win32\debug\ to C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\.

        I copied the mpir.h to C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\.

        The file mpfr.h I copied to C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include.

        Then, I started the Visual Studio and make a new c/c++ console application project. Right click on the Project name on the right side (where all the folders are) and select properties. Then click “configuration properties”, then click “Linker”, and then “Command Line”. After this, in the “Additional options” box I typed mpir.lib and mpfr.lib and then click ok.

        Could you write me what I do wrong?

        There are not in detail information step by step for beginners how to compile source and debug basic example with mpfrc++ library.
        Could you write something like this for VisualStudio2013?

        Thank you,

        Tomas

        • Posted April 10, 2016 at 4:54 pm | #

          You need to create/use x64 configuration for your project (I suspect now you are using Win32). Please google it.

  95. Posted September 7, 2015 at 6:59 am | #

    Version 3.6.2 of mpfrc++ does not implement the modulus operator % nor does it support the (int) operator. Here are the errors emitted:

    g++ FactorRSA.cpp
    FactorRSA.cpp:37:16: error: invalid operands to binary expression
    (‘mpfr::mpreal’ and ‘mpfr::mpreal’)
    if((n % i) == zero) {
    ~ ^ ~
    FactorRSA.cpp:49:19: error: cannot convert ‘const mpfr::mpreal’ to ‘int’ without
    a conversion operator
    k = (int)sqrt(j);
    ^~~~~~~~~~~~
    2 errors generated.

    All of the variables n, i, zero, k, and j are of type mpreal.

    • Posted September 7, 2015 at 11:46 am | #

      1. Operation % is reserved for integer types and undefined for floating point types in C++.
      MPFR C++ is floating point type and hence it doesn’t have %.
      The fmod is probably what you are looking for.

      2. In C++03 there is no way to explicitly disable/enable silent conversions to standard types (e.g. casting to match function arguments, etc.).
      That is why MPFR C++ doesn’t provide them – to disable silent (and probably harmful for accuracy) conversions.

      C++11 resolved this by introducing the explicit type converters. MPFR C++ implements them – please use newer compiler.

      Overall, I believe you use wrong tool for the task. You probably need long integer type for RSA, not the floating-point.

      • Posted September 8, 2015 at 11:43 am | #

        Thanks for your insights, Pavel.

        Despite running OS X and using Apple’s devtools your note to upgrade my C++ compiler is a welcome idea I’ll look into.

        I’m also in agreement with you that I’m using the wrong tool for the job. I found the 128-bit integers available to gcc to be the right fit for the explorations I am going.

  96. quaz0r
    Posted September 25, 2015 at 5:46 am | #

    Hi Pavel, I upgraded from 3.5.9 to 3.6.2 and now most of the mysterious bugs I’ve been plagued with since I started writing my program are gone! One bug persists, but I do not know if it is something wrong with my code or something wrong with mpfr++. I always assumed it was something wrong with my code but I guess that is not necessarily the case. Also, I add the following to mpreal.h for my purposes:

    inline double mpreal::toDoubleExp (long *exp, mp_rnd_t mode) const { return mpfr_get_d_2exp (exp, mpfr_srcptr(), mode); }

    I don’t suppose you would care to officially add something like that?

    • Posted September 25, 2015 at 3:13 pm | #

      Hi,

      1. The C++ standard has special function for this – frexp (and it is implemented in mpfr++).
      Something like:

      mpreal x;
      mp_exp_t exp;

      double d = frexp(x,&exp).toDouble();

      2. What is the bug you cannot get rid of?

  97. Mahesh Naik
    Posted December 20, 2015 at 10:54 pm | #

    Dear,
    I have played with MPFR in the past.I just want to know what latest vs compiler(on windows 7) is usable .i.e. vs2013,vs2015,…
    I have a port of a sanitized version of general polygon clipper which runs only 20-40 times slower with MPFR.
    Mahesh Naik
    mumbai,India
    Maheshnaik.mumbai@gmail.com

  98. Philippe Levesque
    Posted February 9, 2016 at 4:28 am | #

    Really good library. I love. It make life so easier.

    An annecdote;

    Today I was working with mpz constant and was wondering how to transfer the value to a mpreal’s variable,and I just tested with a simple ‘=’ to see it work. **magic** for me.

    • Posted February 9, 2016 at 12:52 pm | #

      You made me laugh :). Thank you for positive start of the day!

  99. Dmitry
    Posted April 20, 2016 at 11:49 pm | #

    Hi!

    I have found problem with MPFR C++/Eigen/Visual Studio 2015 and std::complex.
    Code in the file Eigen\src\Eigenvalues\ComplexSchur.h uses std::abs(std::complex) and std::sqrt(std::complex) that are not defined in the MPFR C++
    Default Visual Studio implementation internally converts arguments to double and completely looses precision;
    Without correct abs and sqrt, modules like Eigenvalues in the Eigen almost useless (in the case of the high precision)
    When i have added these function to MPFR C++, everything has become good

    Code to reproduce problem

    mpfr::mpreal::set_default_prec(512);
    std::cout.precision(32);
    std::complex val(2);
    std::cout<<sqrt(val).real();

    Example of the abs and sqrt implementation:


    #if defined(_MSC_VER)
    namespace std {

    mpfr::mpreal abs(const std::complex& a,
    mp_rnd_t r = mpfr::mpreal::get_default_rnd())
    {
    return sqrt(a.real()*a.real()+ a.imag()*a.imag(),r);
    };

    std::complex sqrt(const std::complex& a,
    mp_rnd_t r = mpfr::mpreal::get_default_rnd())
    {
    if (a.real() == mpfr::mpreal() && a.imag() == mpfr::mpreal()) {
    return 0;
    }

    mpfr::mpreal b, c, d, e;

    b = fabs(a.real(),r);
    c = fabs(a.imag(),r);
    if (b > c) {
    d = c / b;
    e = sqrt(b,r) * sqrt(0.5 * (1.0 + sqrt(1.0 + d*d,r)), r);
    } else {
    d = b / c;
    e = sqrt(c, r) * sqrt(0.5 * (d + sqrt(1.0 + d*d, r)), r);
    }

    std::complex result;
    if (a.real() >= 0.0) {
    result.real(e);
    result.imag(a.imag() / (2.0 * e));
    } else {
    result.imag(a.imag() >= 0.0 ? e : -e);
    result.real(a.real() / (2.0*result.imag()));
    }

    return result;
    }//namespace std

    • Posted April 21, 2016 at 12:33 am | #

      Great, thank you!

      Does the code handle signed zeros in imaginary part correctly? e.g.:

      sqrt(-1 + 0*i) --> 0 + i
      sqrt(-1 - 0*i) --> 0 - i

      Sorry cannot check this myself right now.

      • Dmitry
        Posted April 21, 2016 at 12:53 am | #
        • Posted April 21, 2016 at 11:57 am | #

          There is MPC library, with strict conformance with C99/C++ standards, where signed zero imaginary parts are handled properly.
          But, of course, this is probably not needed in majority of applications and your implementation is efficient. Thank you!
          Definitely somebody will use it.

  100. Musa
    Posted June 12, 2016 at 8:24 am | #

    Dear Povel,

    I am trying to use mpreal for complex numbers but I’m having trouble making it work. I read in the comments that Mark Eggleston used std::complex and worked fine for him. However, I get error when I try to do that. Is there a way that I can use MPFRC++ for complex numbers? Thank you for your great work.

    Regards,
    Musa

    • Posted June 13, 2016 at 4:36 pm | #

      Pavel,

      This may be of use to Musa.

      I did get std::complex to work with MPREAL on Linux but it failed on Windows. I adapted the GNU std::complex implementation for use with MPREAL so that it could be used for both Linux and Windows versions of my software. If you download the source code for Saturn and Titan from the download page of my blog https://element90.wordpress.com/software/downloads/ (saturn-titan-4.2.1.tar.gz) you’ll find a file called mpcomplex.h which handles complex numbers.

      Regards,
      Mark Eggleston

      • Musa
        Posted June 14, 2016 at 6:46 am | #

        Dear Mark,

        Thank you for your help. I actually visited your blog before. Saturn & Titan software that you wrote makes really nice fractals. I’m trying to model the scattering of ultrasound wave and I need to use high precision complex numbers that can work with Boost Bessel functions. I was able to use mpcomplex.h to make multiprecision complex numbers. However, I realized that spherical Bessel function in Boost library called sph_bessel does not let me use mpreal as an input argument type. It seems that I have to use Boost’s version of multiprecision types (mpfr_float). The problem with that is that when you define a complex variable like complex Z, you are not able to work Z with any other argument that has a different type than complex. Is there a way that I can use mpreal.h in Boost sph_bessel?

        Regards,
        Musa

        • Posted June 14, 2016 at 4:58 pm | #

          Musa,

          The way to work with Z with a type of a different type is to construct a multi-precision complex from that type. To use boost functions with multi-precision you have to use their version so you will need to convert to mpfr_float. If you need to mix complex and other number types you can always add suitable methods to mpcomplex.h. I haven’t used boost mpfr_float, it is unfortunate that there isn’t a multi-precision capable boost version of complex as it would save a lot of time.

          Regards,
          Mark

          • Musa
            Posted June 14, 2016 at 10:28 pm | #

            Thank you Mark! That cleared things up for me.

            Regards,
            Musa

  101. Posted June 20, 2016 at 7:33 am | #

    Dear Pavel,

    I am trying to use OpenMP and MPFR C++ together. As a ‘proof of concept’ I am initially using a simple C code that calculates pi, taken from this Tim Mattson’s OpenMP video tutorial. The following code has a double precision pi() function and a multi-precision one using mpreal. It is basically the same except for the variable types. When I compile it, G++ shows me: error: user defined reduction not found for ‘sum’.

    The problem seems to be that OpenMP recognizes C/C++ standard type only — which is expected — but my pragma … reduction indicates a mpreal variable. The question is: is there a way to use OpenMP and MPFR C++?

    Thank you in advance,
    Leonardo Bruno

    [HTML-broken code has been removed]

    • Posted June 20, 2016 at 10:51 am | #

      Dear Leonardo,

      As you correctly noted, OpenMP doesn’t work with non-POD types. But still you can use the MPFR in its basic constructs with more manual work.
      Basic code template:

       mpreal *A,*B;
       ...
       #pragma omp parallel shared(working_precision, rounding_mode,n,A,B...) private(...)
              {
                  int threads = omp_get_num_threads();
                  int id      = omp_get_thread_num();
      
                  int step  = n / threads;
                  int begin = id * step;
                  int end   = (id + 1 == threads) ? n : (id + 1) * step;
      
                  /* set default/working precision in each thread */
                  mpfr_set_default_prec(working_precision);          
      
                 ​ /* set default rounding mode in each thread */
                  mpfr_set_default_rounding_mode(rounding_mode)​;​     ​ 
      
                  mpreal x, y;         
       
                  /* loop to be run in parallel */  
                  for (int i = begin; i < end; i++)
                  {
                      /* do something with A,B, x and y */
                      ...
                  }
                 
                  /* free cache in each thread on exit */
                  mpfr_free_cache(); 
              }
      

      In the code you share only pointers, do the load balancing, etc. by hand.

      • Posted June 20, 2016 at 11:48 am | #

        Hello, Pavel!

        Thank you for the tip. I will try this and as soon as I have any results I tell you about.

        Best regards,
        Leonardo

  102. Ivan
    Posted August 29, 2016 at 9:14 am | #

    Hi Pavel,

    I’ve found some little typo. I got trouble for const variables when using mpfrc++-3.6.2 for exponent manipulations =(( «const mpfr::mpreal» as «this» argument of «mp_exp_t mpfr::mpreal::get_exp()» discards qualifiers.

    Regards,
    Ivan

  103. Vlad
    Posted September 16, 2016 at 9:17 pm | #

    Hello

    …and thank you for this wrapper, it makes things much more clear for beginners, like me. I am trying to make a small program involving polynomials and their roots, so I need to generate and calculate the roots on the fly. One of the polynomials involves factorials and the terms could have been integers, all, but, as I’ve seen in the comments, big integers are not well supported, and floats can be used, instead. So I did, but now I’m facing some strange results and I don’t know what to think now. Consider this simple implementation of a factorial:


    mpfr::mpreal fact(const int &n)
    {
    mpfr::mpreal x(1);
    for (int i=0; i<=n; ++i)
    x *= i;
    return (n==0 ? 1 : x);
    }

    This, when run with i=0..22 works fine, but when it reaches i=23, the results start being wrong. But, as I said, I don’t know what causes them, so I thought I’d first ask you to confirm, or infirm, my findings. My apologies if this turns out to be a mistake of mine.

    Vlad

    • Posted September 16, 2016 at 9:36 pm | #

      Hi Vlad,

      Most probably, MPFR cannot store the result in precision specified. Try setting up higher precision.
      Btw, MPFR C++ has built-in factorial function – fac_ui. Most likely it is much faster than code above.

      • Vlad
        Posted September 16, 2016 at 10:26 pm | #

        You were right, setting mprf_set_drfault_prec(160) corrected the problem (128 was not enough). Thank you for the hints about the builtin functions, and sorry for the noise.

  104. Louis
    Posted January 5, 2017 at 11:56 pm | #

    After a lot of messing around I got it working on Visual Studio 2015. It wasn’t a single header installation. It required 3 header files, a lib file and a dll.

    I tried it on a Mandelbrot and it was impossibly SLOW. Like 600 times longer to run and that wasn’t on a large “zoom” either 🙁

    Thanks for your library but I can’t use it I’m sorry to say.

    • Posted January 6, 2017 at 1:11 pm | #

      MPREAL is one-header C++ wrapper for MPFR library. Of course, the MPFR library itself should be installed first.
      Speed depends on many factors – precision, version of MPFR library you use (Release vs. Debug), capabilities of compiler.
      At the very least you might try using OpenMP to run computations in parallel on all cores of CPU.

    • quaz0r
      Posted January 6, 2017 at 2:14 pm | #

      what are you comparing mpreal to? mpfr without the mpreal wrapper? i dont think so… i think you are comparing it to standard hardware floating point. arbitrary precision is of course much slower than hardware floating point, though gmp/mpfr is about as fast as it can be, utilizing SIMD and all the tricks of the trade. either you need and use arbitrary precision or you dont. there is no free lunch to be had here.

      on the other hand, if you are interested in a mandelbrot free lunch, look into the application of perturbation theory.

  105. Louis
    Posted January 8, 2017 at 1:08 pm | #

    With all due respect….

    I am a newbie to both C++ and Mandelbrot. I used the Intel Compiler to get “long double” for the “evaluation” period with minimal improvement (2E5 approximately?).

    I am using “double” in VS2015 (release not debug) on a 64bit desktop. I am also using standard Windows threading, 6 out of the 8 threads. My test zoom value is 2,073,600 and maxiterations of 25,000. Without mpreal++ the Mandelbrot took 800ms. With the “double” changed to “mpreal” the same Mandelbrot took 578seconds. I was using the default 50 digit define. So mpreal took 722 times as long as stock standard Windows 🙁

    I AM looking at arbitrary precision, perturbation and SuperFractalThing but was hoping to avoid them all by using mpreal++. I am a retired BASIC programmer with assembler skills and DO appreciate the achievement of mpreal++. I started C++ a couple of months ago so AM an absolute newbie, on the coding adventure of my life 🙂

    I CAN reduce my test to 25 digits (temporarily) but hoped to use 50 or 100 digits in the long run. I AM sorry to conclude that mpreal isn’t my solution 🙁

    • quaz0r
      Posted January 8, 2017 at 2:44 pm | #

      again the whole point of perturbation is to make deeper mandelbrot zooms more realistically feasible, as using arbitrary precision to do the standard mandelbrot math is not very feasible. those are in fact your only options though. you wont find a magical arbitrary precision library that is way faster than mpfr or anything like that. all fractal programs including commercial programs that implement arbitrary precision for the standard formula are this slow. either you spend a week(s) to render a deep mandelbrot image this way, or you take the time to implement a perturbation algorithm.

      to put things in perspective, one of the deepest mandelbrot zoom videos prior to the advent of perturbation took upward of a year to render as i recall. whereas the same video could now be rendered in something like a couple days with perturbation.

  106. Louis
    Posted January 10, 2017 at 5:03 pm | #

    Thanks quaz0r, I take your point(s). 🙂

    The jump to perturbation theory (and coding) is HUGE. The jump to mpreal++ is minute hence I WAS hoping it was the solution…. 😉

    I am also wary of the perturbation “glitches” but that has nothing to do with mpreal++. I am sorry mpreal isn’t my solution 🙁

    Thanks for your responses 🙂

  107. Pasquale Tricarico
    Posted January 16, 2017 at 11:04 am | #

    Hi, I just noticed that in mpreal.h v3.6.5 at line 2283, the function tgamma calls

    MPREAL_UNARY_MATH_FUNCTION_BODY(gamma );

    instead of what I would expect:

    MPREAL_UNARY_MATH_FUNCTION_BODY(tgamma );

    I’m not sure what tgamma does compared to gamma, so I’m not sure this is a problem, but just in case. Thanks for this excellent piece of code.

    Pasquale

    • Posted January 16, 2017 at 12:52 pm | #

      C/C++ defines routine name to compute values of Gamma function as “tgamma”. Probably because “gamma” is too common name which might clash with macros (just a guess). MPFR uses “gamma” for Gamma function. There is no difference except the names.

  108. Kevin Hernandez
    Posted February 18, 2017 at 4:11 am | #

    Hi Pavel,

    Thanks for your wrapper. I am having trouble figuring a way to create arrays though:

    mpfr::mpreal *u;
    u = (mpfr::mpreal *) malloc(2*sizeof(mpfr::mpreal));
    u[0] = 1.1;

    is giving a segmentation fault on the assignment to u[0].

    What is the best way to create arrays and multidimensional arrays of mpfr::mpreal?

  109. albert chan
    Posted February 28, 2017 at 1:54 am | #

    mpreal even work for old gcc 3.4.2 mingw ! ( after comment out #include cstdint)

    For win xp, I found out a trick of NOT building gmp, mpfr, mpc … and using little disk spaces.
    google dev cpp mingw, download 4.7.2, you get dll version of gmp, mpfr, mpc for FREE
    when linking to dlls, use -lmpc-2 -lmpfr-1 -lgmp-10

    I get gmp.h, mp*.h from strawsberry perl … then delete them all (384 Mb for perl ?)
    disk spaces used = size of header files (including mpreal.*, of course) = 267 kb

    • Posted February 28, 2017 at 1:27 pm | #

      Great! However I am a bit pessimistic about such an old versions of GMP, MPFR and MPC. especially compiled by such an old GCC.
      Latest versions are way faster.

  110. albert chan
    Posted March 1, 2017 at 5:13 am | #

    my computer is defaulted to x87 64 bit precision.
    do I have to set to 53 bit double precision to use mpfr c++ ?
    (if i set to 53 bits, i cannot use 64 bit long double anywhere)

    mpfr c++ uses mpfr, which uses gmp,
    which may use floating point math, such as for fft multiply …

    do i have to worry double rounding bug ?

  111. albert chan
    Posted March 1, 2017 at 7:15 am | #

    From GMP manual, notes for particular system (section 2.4):
    “The GMP functions involving a double cannot be expected to operate to their full precision when the hardware is in single precision mode”

    It does *not* say more precision (64 bits) is ok
    The problem is floating point math might be involved even for integer multiply.

    My guess is using gmp in directed rounding (e.g. towardzero) is also a BAD idea …

  112. albert chan
    Posted March 1, 2017 at 11:27 am | #

    Tried actually changing precision to 24, 53 and 64 bits AND different rounding modes,
    then generate decimal digits of a BIG prime = 2^57885161 – 1

    GMP is not affected by it (at least my copy, which showed version 5.0.1)

  113. Ivan
    Posted March 2, 2017 at 7:59 pm | #

    Hi Pavel,

    As I know mpreal allocates memory for mantissa dynamically. Can mpreal be customized to allocate mantissa in stack?

    Reqards,
    Ivan

    • Posted March 3, 2017 at 3:54 pm | #

      Hi Ivan,
      Anything can be done, but in this case you would need to customize MPFR since mpreal is just wrapper arpound it.

  114. Ivan
    Posted March 11, 2017 at 4:58 pm | #

    Hi Pavel,
    I’ve found error in division operator realization (line 1516 , version 3.6.5).

    • Posted March 13, 2017 at 4:37 pm | #

      Hi Ivan,
      Thank you very much for the bug report!
      Will be fixed in next commit.

  115. albert chan
    Posted March 13, 2017 at 12:08 am | #

    can mpfr c++ use alias to avoid allocation / copying ?

    mpreal x = “1.2”; … do stuff with x …
    mpreal y = &x; // alias for x, no init or cleanup

    maybe do the same thing with mpfr_t:

    void function(…) {
    static mpfr_t sz = {{._mpfr_prec = 0}};
    if (sz->_mpfr_prec == 0) mpfr_init(sz); // only initialize one time
    mpreal z = &sz; // alias of sz, but mpreal type

    }

  116. albert chan
    Posted March 13, 2017 at 12:46 am | #

    correction on my prev post
    mpreal can alias mpreal, but not mpfr_t
    mpreal x; mpfr_t y; …

    mpreal &xx = x; // ok
    mpreal &yy = y; // error

    • Posted March 13, 2017 at 4:32 pm | #

      1. You just need to follow C++ rules to create an alias:

           mpfr_t y;
           mpfr_init_set_d(y,10,MPFR_RNDN);
      
           mpfr::mpreal& x = *reinterpret_cast<mpfr::mpreal*>(&y);  // x is an alias for y
      
           x += x;
           std::cout << "x = " << x << std::endl;
      
           mpfr_clear(y);
      

      2. MPREAL even has special constructor to take ownership of existing ‘mpfr_t’ without re-allocations:

      mpreal(const mpfr_t  u, bool shared = false); 

      3. However all these techniques can be avoided, since MPREAL variable can be used interchangeably with ‘mpfr_t’:

           mpfr::mpreal x(10), y(20), z;
      
           z = x+y;
           std::cout << "C++:  z = " << z << std::endl;
      
           // Use MPREALs with native MPFR functions:
           mpfr_add(z.mpfr_ptr(), x.mpfr_srcptr(), y.mpfr_srcptr(), MPFR_RNDN); 
              
           std::cout << "MPFR: z = " << z << std::endl;
      
  117. Paul Hentschel
    Posted June 5, 2017 at 9:45 am | #

    Hi Pavel,

    First of all, thank you for this wrapper. I have just finished setting it up in Visual Studio 2017.

    Just a heads up, mpfr_grandom is deprecated in the latest dev version(4.0.0) of mpfr which caused my build of example.cpp to fail.
    https://github.com/BrianGladman/mpfr/blob/master/NEWS.
    I ended up using the dev version of mpfr because it had a solution file for VS 2017.
    Adding #pragma warning(disable : 4996) to mpreal.h will get example.cpp to build (with VS 2017).

    New functions mpfr_nrandom and mpfr_erandom were added for random number generation. It looks like mpfr_nrandom is the replacement for mpfr_grandom, so changing line 2646 from
    mpfr_grandom(x.mpfr_ptr(), NULL, state, rnd_mode);
    to
    mpfr_nrandom(x.mpfr_ptr(), state, rnd_mode);
    also seems to work as a quick fix, but I haven’t done any testing other than to see if it would build without error.

    Thanks again!
    Paul

    • Posted June 5, 2017 at 10:16 am | #

      Hi Paul,

      Thank you very much for your feedback and suggestions!
      If you want, you can commit your changes using pull request to mother repository: https://bitbucket.org/advanpix/mpreal/

      Just out of curiosity, what do you use mpfr/mpreal for?
      Your company name includes “precision”, do you use arbitrary-precision computations in practical applications?

      • Paul Hentschel
        Posted June 6, 2017 at 3:06 am | #

        Hi Pavel,

        I forked your repository yesterday and have made a change that I think may work. I’ll try doing the pull request tonight and let you have a look. I ended up building the supporting libraries in Msys/MinGw so I could test my change with g++ and the release version (3.1.5) of mpfr without switching back and forth from Windows to Linux.

        Right now I am just playing with the software for personal knowledge. I have been writing some functions for working with Bezier curves, and eventually b-splines. While I was writing a function for estimating the arclength of splines using Gauss-Legendre quadrature, I got curious about the higher precision used to calculate the weights and abscissa tables I was finding online, which eventually led me here. So I haven’t actually used the software yet, other than testing my setup.

        My business is machining, so the “Precision Machining” in the name does not involve the accuracy of arbitrary-precision computations. I work to 4 place decimal tolerances (inches), but most of my work involves 3 place tolerances. Most of my software projects, which are more of a hobby, are centered around writing plugins for my CAD system and generating toolpaths for my CNCs.

        Thank you,
        Paul

  118. Paul Hentschel
    Posted June 6, 2017 at 5:04 am | #

    Pavel,

    Upon further review, I’m not sure about mpfr_grandom being deprecated on the official version. I was using Brian Gladman’s github repository here: https://github.com/BrianGladman/mpfr, which is where I got the information I mentioned before. His repository has a version number of 4.0.0-dev. The official repository has the latest branch as 3.1.6-dev (as far as I can tell), and I can find no mention of the deprecation in the log. My proposed change may still be ok so I will add pull request. Just wanted to make you aware of the situation.

    • Posted June 6, 2017 at 5:34 pm | #

      I have no doubts about deprecated status of mpfr_grandom in 4.0.0. MPFR has been warning about this for the last few releases (in documentation and in comments). I think we can proceed with this change. The main thing is to maintain backward compatibility – ancient versions of MPFR are being used in many places.

      As for Gauss-Legendre quadrature, here is good paper summarizing various approximations for Legendre roots: http://eprints.maths.ox.ac.uk/1629/1/finalOR79.pdf

      I have Gauss-Legendre code myself: https://goo.gl/iQZ42R
      It can be easily converted to mpreal, just in case :).

      However I would suggest to use adaptive Gauss-Kronrod instead. It subdivides integration interval recursively, estimates integral & approximation error on each of intervals, and continue with subdivision until target accuracy level is reached.
      So that it is able to integrate functions far from polynomials and most importantly it guarantees accuracy of approximation.

      • Paul Hentschel
        Posted June 7, 2017 at 4:57 am | #

        The change I made shouldn’t affect backwards compatibility.

        Thank you for the links and for the suggestion about adaptive Gauss-Kronrod. I am very interested in learning it. I will need to do some research to understand what it is and how to code it.

  119. Frank
    Posted June 14, 2017 at 4:25 am | #

    I am attempting to use mpfrcpp with mlapack to do matrix exponentiation. if I have a fairly sparse matrix M_512x512 and take powers M^2, M^4, M^8 it is all very fast, however, if I am taking it to much higher powers M^128, M^512, the time for the operation goes way up.

    M^2 took 72 milliseconds
    M^4 took 109 milliseconds
    M^8 took 93 milliseconds
    M^16 took 116 milliseconds
    M^32 took 231 milliseconds
    M^64 took 450 milliseconds
    M^128 took 1357 milliseconds
    M^256 took 15320 milliseconds
    M^512 took 55050 milliseconds

    Compare this with the same matrix in Octave, and the results never have the large increase:

    octave:516> id=tic(); m^2; toc(id);
    Elapsed time is 0.189081 seconds.
    octave:517> id=tic(); m^4; toc(id);
    Elapsed time is 0.277484 seconds.
    octave:518> id=tic(); m^8; toc(id);
    Elapsed time is 0.371387 seconds.
    octave:519> id=tic(); m^16; toc(id);
    Elapsed time is 0.510126 seconds.
    octave:520> id=tic(); m^32; toc(id);
    Elapsed time is 0.662008 seconds.
    octave:521> id=tic(); m^64; toc(id);
    Elapsed time is 0.52304 seconds.
    octave:522> id=tic(); m^128; toc(id);
    Elapsed time is 0.750484 seconds.
    octave:523> id=tic(); m^256; toc(id);
    Elapsed time is 0.905318 seconds.
    octave:524> id=tic(); m^512; toc(id);
    Elapsed time is 1.14177 seconds.

    Would you have any idea what optimizations Octave is doing that keeps this from happening, or methods I could use to achieve similar results using mpfrcpp?

    • Posted June 14, 2017 at 10:27 am | #

      Frank, I have no relation to mplapack, nor octave.
      All of these pieces of software are open source and you can actually see how they do any of the operations.

      In general, matrix power can be done in several ways: (a) binary squaring (if power is integer); (b) using Schur-Parlett (Schur decomposition is required) or (c) using expm/logm if you have such routines. For details you can check the following reference:

      P. I. Davies and N. J. Higham, A Schur-Parlett algorithm for computing matrix functions. SIAM J. Matrix Anal. Appl., 25(2):464-485, 2003.

      If you are looking for ready-to-use library to compute matrix functions in arbitrary precision – then Multiprecision Computing Toolbox for MATLAB would be the best bet (see mpower, logm, expm, funm). All open source alternatives are ages behind in quality, speed and functionality.

  120. Hannes
    Posted July 4, 2017 at 6:38 pm | #

    Hi Pavel,

    from what I understand, adding two values of different precision yields a value that has the precision of the minimum of the two addded values. If this is correct, what is the behavior in the following example
    double x = 3.14;
    mpreal y = static_cast(1)/static_cast(3);
    mpreal sum = x + y;
    If I understand mpreal correctly, the double value ist casted to mpreal and then x and y are added. Does sum has the precision of x? I assume, if I set the default precision with mpreal::set_default_prec, this guarantees that x and y have the same precision.

  121. zzh
    Posted July 20, 2017 at 12:46 pm | #

    I faced a little problem when I used it to modify my code for the MPFR version.

    for( long inx = 0, y = 0; y < bitmap.h(); ++y)
    {
    for( long x = 0; x < bitmap.w(); ++x, ++inx)
    {
    mpreal r = 0.0, g = 0.0, b = 0.0;
    for( long n = 0, j = -radius; j<= radius; ++j)
    // do something with r,g,b..
    }
    }

    when I compiling it ,it shows the following error:
    GNU MP: Cannot allocate memory (size=451066975599404656)
    Aborted (core dumped)

    PS: x, y are the image of the length and width of the pixel value in this loop, and finally will reach 480,640.

  122. Heinz
    Posted August 3, 2017 at 4:10 am | #

    Beside the limitations of C++ very useful product.
    Using g++, a restricted use of mpreal global variables is possible in program text before main, but after e.g.:

    bool init(int i) { cout << "** mpreal initialized #" << i << endl;
    mp_rnd_t mode = MPFR_RNDN;
    mpreal::set_default_prec(mp_bin_digits);
    mpreal::set_default_rnd(mode); // set rnd_mode GMP_RNDN
    return true;
    };
    const bool initialized_1 = init(1);

    Without this modifications it would have been nearly impossible to make my program flexible (mpreal or long double as default real type; template definitions for all classes and most functions – both a painful exercise because of the C++ type concept, overloading and implicit conversions, making specially crazy and tricky solutions necessary for templated constant definitions.

    There's a little error giving some bigger problem:
    Any try to read complex values which are wrote before is ending in error.
    The cause is simple: standard output e.g. of complex (1,2) is .. (1,2). MPREAL can’t process that, but can it process it with blank before comma and ‘)’.
    It would be helpful, if it’s possible to correct this problem.

    I’d given an evaluated example, but there are some crazy text modifications.

  123. Tomas
    Posted February 24, 2018 at 2:09 am | #

    Hi,
    I’m trying to use MPFRC++ and Eigen to compute the eigenvalues of a non-symmetric matrix with high precision. The test code for the LU-decomposition and for the symmetric eigenvalue problem run without a problem. However, when try the code (which I name testEigen.cpp):

    #include
    #include
    #include
    using namespace mpfr;
    using namespace Eigen;

    int main()
    {
    mpreal::set_default_prec(256);
    typedef Matrix MatrixXmp;
    MatrixXmp A = MatrixXmp::Random(100,100);
    A.eigenvalues();
    }

    and compile it using

    g++ -I eigen-3.3.4 -I eigen-3.3.4/unsupported -I eigen-3.3.4/unsupported/test/mpreal -lmpfr -lgmp testEigen.cpp -o testEigen

    (where g++ is “Apple LLVM version 9.0.0 (clang-900.0.39.2)” ) I get the error:

    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/complex:679:20: error: cannot convert 'mpfr::mpreal' to 'int' without a conversion operator
    __ilogbw = static_cast(__logbw);

    After reading the questions and answers above, I gather that the error occurs because 1) non-symmetric matrices can have complex eigenvalues and this is implemented in Eigen using std::complex, 2) std::complex requires some conversions to simpler datatypes, 3) such conversions are risky since it may lead (on some systems) to loss of precision without a warning, 4) you therefore removed the conversions and caution against using MPFRC++ and std::complex. Is this correct? Does this preclude using MPFRC++ to compute the eigenvalues of non-symmetric matrices?

    I am also a bit confused about why the conversion fails; the file Eigen/MPRealSupport (which I assume is related to Konstantin Holoborodko’s mpreal_eigen.h mentioned in previous questions) contains the definition:

    template inline int cast(const mpfr::mpreal& x) { return int(x.toLong()); }

    It seems to me like this line should take care of the conversion operator, but this level of C++ is a bit beyond me.

    In a comment from a couple of years ago you mentioned that you may develop mpcomplex. I think this would be appreciated by a lot of people, especially if integrated with Eigen. In any case, thank you for developing this useful package.

  124. Sachin Krishnan
    Posted November 20, 2018 at 2:59 pm | #

    Hello Pavel,

    Thank you for this excellent C++ wrapper.

    Since MPFR version 4.0.0, the functions mpfr_root and mpfr_grandom has been deprecated.

    Changing the line 2201 from
    mpfr_root(y.mpfr_ptr(), x.mpfr_srcptr(), k, r);
    to
    mpfr_rootn_ui(y.mpfr_ptr(), x.mpfr_srcptr(), k, r);

    and line 2646 from
    mpfr_grandom(x.mpfr_ptr(), NULL, state, rnd_mode);
    to
    mpfr_nrandom(x.mpfr_ptr(), state, rnd_mode);

    will stop the compile time warnings.

    Thanks again!

  125. Anirban
    Posted January 23, 2019 at 5:04 pm | #

    I was able to compile a static MPIR lib on using Visual Studio 2017, but failed with MPFR.

    The blob MPFR-MPIR-x86-x64-MSVC2010.zip has only DLLs — could I request a static MPFR library please?

    AB

  126. Posted May 23, 2019 at 12:13 am | #

    Ahoj Pavel,
    Srdečné díky od Řezna!

    I was looking for a C++ wrapper for mpfr, stumpled over your version and implemented and compiled my program with 4 trials successfully! Much better is impossible. So thanks a lot for such high quality code.

    (and excuse the preceding czech words, but your name suggests czech origin.

    • Posted May 23, 2019 at 10:51 am | #

      Hi Frank!
      Thank you for your positive feedback – I appreciate it very much!
      You are right, I am of Slavic ethnicity and I can understand your greeting.

      Czech is not my native language, since originally I am from Ukraine…
      Although we use Cyrillic characters, pronunciation and meaning of the words are very close.

  127. frank
    Posted May 27, 2019 at 5:01 pm | #

    Hi Pavel,

    two changes, to avoid deprecated functions in mpfr:

    1. line 2646: mpfr_nrandom(x.mpfr_ptr(), state, rnd_mode); // instead of grandom
    2. line 2201: mpfr_rootn_ui(y.mpfr_ptr(), x.mpfr_srcptr(), k, r); // instead of root

    I tested both changes with my application

    Frank

  128. Yanislav Vasilev
    Posted May 27, 2019 at 7:26 pm | #

    Hi Pavel,

    I am new to arbitrary precision calculations and I would like to ask a few questions.
    I am using boost::multiprecision wrapper of mpfr and mpir for calculating pi using Ramanujan’s formula for one of my school projects. I am also new to C++ as you might guess later, so
    – I was wondering is it worth making my code using simd instructions or mpfr uses them internally already?
    – If it makes sense to use simd what library would you suggest me to do it, cause I tried xsimd so far and it seems to be not working with mpfr type at first glance (like I said I am not really experienced C++ developer in order to debug external libraries and understand where the problem is)

    Yanislav

    • Posted May 28, 2019 at 12:27 pm | #

      Vectorization instructions are designed for standard types implemented in hardware.
      You cannot use high-level MPFR/MPIR types with SIMD.

      P.S. My library (MPFR C++) has no relation to boost::multiprecision. Please use their forum for related questions.

  129. TheRammer
    Posted October 28, 2020 at 11:41 pm | #

    Is this project dead? Example doesn’t even compile for me. Perhaps user error?

    -*- mode: compilation; default-directory: “~/Downloads/mpreal-master/example/” -*-
    Compilation started at Wed Oct 28 09:39:33

    make
    g++ -c example.cpp
    In file included from example.cpp:50:
    ./../mpreal.h:2621:11: error: cannot convert ‘mpfr::mpreal’ to ‘long’ without a
    conversion operator
    r = long(x);
    ^~~~~~
    ./../mpreal.h:2630:11: error: cannot convert ‘mpfr::mpreal’ to ‘long long’ without a
    conversion operator
    r = (long long)(x);
    ^~~~~~~~~~~~~~
    2 errors generated.
    make: *** [example.o] Error 1

    Compilation exited abnormally with code 2 at Wed Oct 28 09:39:34

    • Posted October 29, 2020 at 4:43 pm | #

      No, it is not dead. What version of gcc are you using?
      I suppose we need to enable C++11 mode during compilation.

  130. Rabie
    Posted December 22, 2021 at 9:44 am | #

    Hi Mr. Pavel,

    I am dealing with log() accuracy problem. I got the different log(x) values when computed when using your MPFR wrapper versus Python Decimal class. For instance, when I calculate log(2),

    log(mpreal(“2”)) = 0.69314718055994528622676398299518041312694549560546875 when using MPFR C++

    but

    log(decimal.decimal(‘2’)) = 0.6931471805599453094172321214581765680755001343602552541 when using Python Decimal.

    Digit disagreements begin after 15 decimal points…
    Could you help me explaining the reason and how to rectify this problem. I feel like it is more likely that the error is coming from me, but I couldn’t find the source of the problem.

    Thanks,
    Rabie.

    • Posted December 22, 2021 at 11:00 am | #

      What precision do you use in MPFR C++?

      • Rabie
        Posted December 22, 2021 at 3:08 pm | #

        Hi Mr Pavel,

        Thanks for your reply. I have set to 400 digits precision via:

        mpreal::set_default_prec(digits2bits(400));

        Maybe I did something wrong?

        • Posted December 22, 2021 at 5:05 pm | #

          The Python result is correct. MPFR C++ computes result correctly as well.
          There is something wrong in your code – e.g. you converted mpreal result to double during output or something like this.

          • Rabie
            Posted December 22, 2021 at 5:51 pm | #

            Hi Mr. Pavel,

            Thanks very much. There was a fault in my code where I accidentally did not set the precision earlier. My bad. I managed to solved it. I apologize for bothering you. I really appreciate for your help, and again, your C++ wrapper really helps me and my research!

            Regards,
            Rabie

  131. Ilya
    Posted February 9, 2022 at 8:55 am | #

    Hi Pavel,

    I am trying to follow Thomas Kim’s video https : //www . youtube . com/watch?v=SoBVqS2lN7E using Visual Studio 2019.
    At compilation, I am getting a number of similar errors like
    1>C:\Dev\gmp-vs2019\mpfr\x64\Release\mpreal.h(590,27): error C2660: ‘mpfr::mpreal::mpfr_srcptr’: function does not take 1 arguments
    1>C:\Dev\gmp-vs2019\mpfr\x64\Release\mpreal.h(324,19): message : see declaration of ‘mpfr::mpreal::mpfr_srcptr’
    1>C:\Dev\gmp-vs2019\mpfr\x64\Release\mpreal.h(590,57): error C2660: ‘mpfr_init2’: function does not take 1 arguments
    1>C:\Dev\gmp-vs2019\mpfr\x64\Release\mpfr.h(445,22): message : see declaration of ‘mpfr_init2’
    1>C:\Dev\gmp-vs2019\mpfr\x64\Release\mpreal.h(624,32): error C2660: ‘mpfr::mpreal::mpfr_srcptr’: function does not take 1 arguments
    1>C:\Dev\gmp-vs2019\mpfr\x64\Release\mpreal.h(324,19): message : see declaration of ‘mpfr::mpreal::mpfr_srcptr’

    Could you give me a hint on how this can be resolved?
    I tried to apply different C++ language standards in my project, C++14 and 17.

    Thank you
    Ilya

  132. Ted Malliaris
    Posted October 26, 2022 at 7:15 am | #

    Hi Pavel,

    Thanks so much for this wonderful library — has been very useful! Not critical, but I was hoping to use both mpreal’s and a few routines from the FLINT library, and both rely on MPFR. I’m getting a name conflict when trying to compile the minimal example below. System is Debian 10 with all libraries installed from the standard repositories, e.g., libmpfrc++-dev, libflint-dev. I’m comfortable at the cmd line, but not at the level of writing libraries… is there an easy way around this? test.cpp contains:

    #include <mpreal.h>
    #include <flint/flint.h>

    int main() {

    return 0;
    }

    and running with command “g++ test.cpp” gives output:

    In file included from test.cpp:2:
    /usr/include/flint/flint.h:217:23: error: ‘typedef struct __mpfr_struct mpfr’ redeclared as different kind of symbol
    typedef __mpfr_struct mpfr;
    ^~~~
    In file included from test.cpp:1:
    /usr/include/mpreal.h:147:11: note: previous declaration ‘namespace mpfr { }’
    namespace mpfr {
    ^~~~

  133. Oren Bassik
    Posted January 5, 2023 at 1:35 pm | #

    Dear Pavel,

    Thank you for this excellent wrapper. There is some discussion above about serialization which I would love some more of your thoughts on. What do you recommend if I have a short-term need to serialize some mpreal objects? For detail
    1) round-trip guarantee is important, and copied objects should have the same serialization (assuming global state unchanged)
    2) speed, size not important
    3) I have no objection to “going down” to mpfr or gmp underlying variables if necessary.

    I was thinking to use strings (to_string()) in base 2, with n=precision+2, and a fixed rounding mode. However I am not confident that (1) will be satisfied. Do you have any recommendation?

  134. Alexsei Lektchinov
    Posted June 20, 2023 at 11:10 pm | #

    Hi Pavel,

    Developers of mpfr C original interface mentioned that library internally allocates a lot of memory on the stack. I came across some comments claiming that under some extensive usage of mpfr function calls there could be a possibility that your program runs out of stack space and ends up crushing. Have you ever experience such condition? Is that possible?
    I am planning to use your library by making C style wrappers in a way like:

    double addDbl(double target, double op)
    {
    mpfr::mpreal mtg(target);
    mpfr::mpreal mop(op);
    return (mtg + mop).toDouble();
    }

    So the idea is still to use the existing ‘double’ type in the legacy application whereas using internally your C++ mpreal type and getting more precise result saved back to the legacy ‘double’ type variable. But along the way obviously there is a lot of on-stack allocations take place. Can you think of any potential problems?

    Thank You in advance

    • Posted June 21, 2023 at 1:15 pm | #

      MPFR frees any space it allocates, especially on stack (stack is freed automatically on function return). So that unless you do millions of recursive calls, you are fine. The idea of using MPFR to do double operations makes no sense. Accuracy of the final result will be limited to double precision anyway.

      That is because you truncate the result back to limited precision (any extra digits are lost). Rounding errors accumulate over multiple operations. Hence, if you truncate result on each operation – rounding errors will be the same. Cancellation errors won’t be cured too.

      To boost up the accuracy, all operations must be done with arguments in “true” extended precision. Can you port your code to be scalar-invariant (use scalar type as template)?

      • Alexsei Lektchinov
        Posted June 22, 2023 at 3:15 am | #

        Yes, you’re absolutely right, – if multiple operations converting double ->mpreal->double take place during multiple calculations the precision will be fading to say the least… Although when I ran my sample doing that with a few hundred input lines the final calculation result was accurate (to my requirements) even I did apply conversions double ->mpreal->double. I cared in that particular case for precision of 10 significant digits for double. Which is below 16 digits provided by the standard for double type. Whereas calculating with mere double type failed.
        So, would you say that no matter how I set up mpreal precision if I operate through the mentioned above function conversions (we can call them barbaric..?) the 10 digits of precision for final double still can be incorrect?
        The ultimate goal is to move the legacy application to use mpreal for calculations. But to make it in a single step is impractical… Too many dependencies and API using still double.

      • Alexsei Lektchinov
        Posted June 22, 2023 at 7:08 am | #

        Since the app input is always a string of finite number of digits a better option would be to define some temporary API in terms of const char* / std::string with return value of mpreal?
        Like:
        mpreal addMp(const char* x1, …);
        mpreal mltMp(const char* x1, …);
        …..
        Thus expression like addMp(x1, addMp(x2, mltMp(x3, addMp(x4,x5)))) would be valid and provide still better precision than in case of mere double type?

        • Posted June 22, 2023 at 5:05 pm | #

          For 10 digits of precision, the approach might produce better accuracy compared to using plain double. That is because MPFR arithmetic does better rounding of a last digits of the result (and provides wider exponent range in general).

          As for the using the strings. Conversion to strings back and forth is extremely costly operation for floating-point numbers. Speed will be reduced by several orders of magnitude.

          Still, I see no better way, than converting the computational to scalar-invariant C++. The operator overloading will minimize the required code changes.
          Whereas re-writing the code to use custom addMp, mlyMp, etc. would require much more changes, time and efforts.

          Contact me by email (pavel@holoborodko.com) if you want my help on a professional terms.

  135. Sampo Paukkonen
    Posted August 1, 2024 at 8:27 pm | #

    Dear Pavel,

    The work you have done is very impressive and the MPFR C++ project is exactly what I am looking for a scientific computation related task. I just have one trivial question that I could not determine myself based on the given documentation and the existing source code. Specifically, what is the proper type to be used for arbitrary precision integers? In the project that I am working in, we have to iterate over a large range of integers and perform computations for them, with the upper bound being in the range of 3^{55}. For this it would be the most convenient if we would run a for-loop over w.r.t. some variable i over this range with i having a type that allows one to represent numbers in the range of 3^{55}. I already tried to use the mpreal type, but at some points of the program we have to read data from (possibly large) indices, and as of writing reading data from a type const std::vector array with a type mpfr::mpreal caused the error that “error: no match for ‘operator[]’”, when data is being read as data[i] and i having a type mpfr::mpreal. If all else fails I suppose one fix could be iterate over the data structure and make appropriate changes to the code.

    Best,
    Sampo

    • Posted August 1, 2024 at 11:48 pm | #

      Dear Sampo,
      Please note, you should use at least 88-bit precision to be able to represent numbers of 3^55 magnitude (log2(3^55)~88). The std::vector supports only indices of the standard types – 32 and 64 bit integers. Even if you would overload the std::vector::operator[] to support mpfr::mpreal – this would make no sense since you are dealing with 88-bit indices (not representable in 32/64 bits).

      Overall, the mpfr::mpreal type is floating-point type, hence it is not good idea to use as an integer.
      You need library for long integers (probably 128-bit integer would cover your needs). The GCC compiler has built-in 128-bit integers: __int128_t. Or you can use mpz_t type from MPIR/GMP libraries.

      • Sampo Paukkonen
        Posted August 6, 2024 at 7:25 pm | #

        Dear Pavel,

        Thank you for your response. I would like to additionally ask whether any vector-type data structures in C++ (or MPFR) allow using at least 88-bit precision indices? Or is it that if you have to use any of the extending numerical types, you essentially have always to write a C-style wrapper and use arrays? I am new to extending numerical libraries with standard C++ code, so this question might be a bit naïve, feel free to direct me to any resource better suited for this (I could not find any such guide online).

        Best,
        Sampo

        • Posted August 6, 2024 at 11:02 pm | #

          Dear Sampo,

          There is no actual need to support indices beyond 64 bits. Let’s say you operate with “double” numbers (8-byte). Then in case of 64-bit index, vector capacity can be 8*2^64 bytes, which is ~128 Exabytes. This covers all possible needs, and there is no need for higher bit indices. In case of extended precision numbers, it is even worse (much, much worse). Therefore it is much easier to just allocate your array and index it with realistic 32 or 64-bit index.

          C/C++ is all about performance and such nitty-gritty details are very important.

  136. Sampo Paukkonen
    Posted August 7, 2024 at 10:32 pm | #

    Dear Pavel,

    In the application I am working, I would like to use both mpz_t (technically of type mpz_class as per: https://gmplib.org/manual/C_002b_002b-Interface-Integers) and mpreal type variables. Occasionally, I have to do some arithmetic with both of these types together that would result in a real number, and so it should be stored to a type mpreal. As of writing I having some difficulties implementing the desired behavior. For example, in much the simplified code below:


    mpr computation(const int & e, const mpz & m) {

    const mpr modder { mpfr::pow(mpfr::mpreal(3), mpfr::mpreal(e)) };

    const mpr m_mod = mpfr::mod(m, modder);

    return m_mod;
    }

    I get the error message:


    extended_main.cpp: In function ‘mpr computation(const int&, const mpz&)’:
    extended_main.cpp:80:33: error: invalid initialization of reference of type ‘const mpfr::mpreal&’ from expression of type ‘const mpz’ {aka ‘const __gmp_expr’}
    80 | const mpr m_mod = mpfr::mod(m, modder);
    | ^
    In file included from extended_main.cpp:14:

    where the line 80 refers to the line where m_mod is defined. The same issue persists even if I change the code to:

    mpr computation(const int & e, const mpz & m) {

    const mpr modder { mpfr::pow(mpfr::mpreal(3), mpfr::mpreal(e)) };

    const mpr m_mod = mpfr::mod(mpfr::mpreal(m), mpfr::mpreal(modder));

    return m_mod;
    }

    My questions are:

    1.) How should the code be modified to avoid compilation errors?

    2.) If one has to do simple arithmetic computations that mix mpreal and mpz_class variables, what is the best way to correctly map the operands to types supported by MPFR C++?

    Best,
    Sampo

    • Sampo Paukkonen
      Posted August 13, 2024 at 4:38 pm | #

      I am posting this follow up comment in the case that someone else is working on a similar application and has the same problem: how to mix GMP’s integer type class for C++ with MPFR C++’s mpreal class. For me, it was just easiest to switch everything to mpreal throughout the program. For us, there was no need to use index variables with mpreal or a similar extended number type since you would run out of memory sooner on a 64-bit machine than out of integer precision for storage variables. In the event that you have to generate larger integers than 2^{64} - 1, you could perhaps first generate some of them up to standard C++ limits and then reprocess those numbers further as mpreal type variables.

  137. William James
    Posted October 14, 2024 at 9:22 am | #

    The digits2bits call has an argument of type int which on a current Mac with Xcode is a 4 byte integer. Recommend that it be changed to a mp_prec_t so that it can be a long which should be an eight byte integer. Without this, the digits2bits call will limit the bit precision to be 32 bits on some systems.

    Bill James

    • Posted October 14, 2024 at 12:26 pm | #

      The argument is a number of decimal digits. Function translates it to the precision in bits. The maximum value of ‘int’ is 2,147,483,647 – that is a lot of decimal digits (~7.13GB would be required to store one number). Do you really have a need to upgrade it to 9,223,372,036,854,775,807 decimal digits?

      • William James
        Posted October 14, 2024 at 7:42 pm | #

        Yes, if for instance you want to compute pi or another constant to billions of decimal places you need more than 2 billion digits. MPFR currently has some bugs that is preventing large bit precisions from working on some platforms but they are investigating fixes. My laptop for instance has 128 GB of memory and I experiment with large numbers all the time.

        • Posted October 14, 2024 at 8:39 pm | #

          I guess it is not efficient to compute constants with such precision using MPFR. How long does it take to compute “pi” with 2^31-1 precision?

          • William James
            Posted October 15, 2024 at 11:06 pm | #

            To compute 667127569 decimal digits of pi using a simple Arithmetic Geometric Mean algorithm took 1421.98 seconds on an Apple MacBook Pro with M3Max chip. With the digitstobits argument change I can compute much larger digit counts. But when I hit 2^31 digits the toString() call fails for the int/long issue with it as well.

2 Trackbacks

  1. […] my concerns.  But there is a tiny problem. MPFR is based on native C style. and its not so easy. MPFR++ is a C++ wrapper to the native MPFR. If you want to use this, you have to include the files with […]

  2. […] Edición: El MPFR contenedor de C++ página contiene información, enlaces a GMP/MPFR soluciones de Visual Studio y compilado gmp/mpfr de las bibliotecas, así: http://www.holoborodko.com/pavel/mpfr/ […]

Post a Comment

Your email is never published nor shared.

Use native LaTeX syntax to include formulas: $ ... $, \[ ... \], etc. Do not forget to preview comment before posting.

Also you may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Subscribe without commenting