MPFR C++

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:

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

You are welcome to participate in MPFR C++ development. Here is MPFR C++ Mercurial repository.

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++

Multiprecision Computing Toolbox allows existing MATLAB programs to run in arbitrary precision – with little to no modifications to the source 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 (6 votes, average: 5.00)
Loading ... Loading ...
Print This Page Print This Page

246 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

  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 :P

            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

  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.

One Trackback

  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 […]

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=""> <strike> <strong>

Subscribe without commenting