MPFC++ wrapper by Pavel


这个工具非常不错。把超过double的高精度计算在C++中的实现变得方便容易了。

mpir, mpfr, mpf, eigen C++ template library

http://www.holoborodko.com/pavel/mpfr/

MPFR C++

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

?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
// 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:

?
1
2
3
4
5
// 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 ofdouble or float types. See example in distribution for more information.

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

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

Software using MPFR C++

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

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

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

Internals

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

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

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

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

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

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

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

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

Acknowledgements

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

History

April 11, 2010:

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

November 8, 2010:

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

October 5, 2010:

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

July 15, 2010:

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

June 15, 2010:

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

May 21, 2010:

August 31, 2009:

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

May 11, 2009:

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

March 9, 2009:

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

November 18, 2008:

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

October 1, 2008:

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

September 30, 2008:

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

September 29th, 2008:

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

September 4th, 2008:

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

August 15th, 2008:

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

August 14th, 2008:

  • Add: division operators when first operand is double.

August 11th, 2008:

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

August 8th, 2008:

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

August 5th, 2008:

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

August 4th, 2008:

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

July 11th, 2008: Project start.


1 Star 2 Stars 3 Stars 4 Stars 5 Stars  ( 8  votes, average:   5.00)

268 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.

        • Posted August 31, 2009 at 7:59 pm   |   #

          You should define static class member globally (not inside function):

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

          Please check this great site for explanation:
          http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.11

  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

      ?
      1
      2
      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):

      ?
      1
      2
      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:

      ?
      01
      02
      03
      04
      05
      06
      07
      08
      09
      10
      11
      12
      13
      14
      15
      16
      17
      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:

        ?
        1
        2
        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:

        ?
        1
        2
        3
        4
        5
        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

        ?
        1
        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:

      ?
      1
      2
      3
      4
      #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.odlmalloc.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:

      ?
      1
      2
      3
      4
      5
      6
      7
      namespace boost {
           template <>
           inline mpfr::mpreal lexical_cast( const std::string& arg)
           {
               return mpfr::mpreal(arg);
           }
      }

      Then conversion works nicely:

      ?
      1
      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:

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

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

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

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

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

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

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

            I made the following modification.

            1. add the following code in mpreal.hpp

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            Hi Tsai, thank you for you suggestions.

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

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

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

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

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

    Dear Mr Holoborodko

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

    Sincerely yours Valdes Coosk , Vilnius.

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

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

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

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

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

    See complete source code….

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

    Best wishes
    Isaia

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

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

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

    Hi Pavel,

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

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

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

      Hi,

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

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

        Hi Pavel,

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

        Thanks

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


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

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

    Hello Pavel,

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

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

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

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

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

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

    Thanks for your help,
    Philippe

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

      Philippe,

      Thank you for your bug report!

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

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

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

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

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

        Pavel,

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

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

        Thanks a lot!
        Philippe

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

          Fixed. BTW what happens if you activate int64?

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

            Well I get lots of:

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

            and related redefinitions errors and:

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

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

            Hilarious output!
            What is version of gcc you have?

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

            Its gcc-4.4.5

            I can try on another machine…

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

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

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

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

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

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

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

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

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

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

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

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

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

            Sorry to bug you with so many questions.

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

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

            yes, these are x64 machines/systems.

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

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

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

            So, you have full-featured multiprecision support.

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

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

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

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

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

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

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

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

    What is going on?

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

    Thank you.

    Javier

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

      Javier,

      Comment this line in mpreal.h as temporary measure:

      #define MPREAL_HAVE_INT64_SUPPORT // int64_t, uint64_t support

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

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

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

        Pavel,

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

        The solution you proposed works fine.

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

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

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

        Allow me more questions:

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

        Many thanks.

        Javier

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

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

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

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

    Pavel,

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

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

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

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

    Note: my operating system is Windows 7 64 bits.

    Thank you,

    Javier

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

    Hi,

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

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

    Regards,
    Vinayak

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

    Hi, Pavel,

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

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

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

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

    Cheers,

    Li

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

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

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

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

        Thanks!

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

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

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

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

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

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

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

            Yes, works now~ Thanks!

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

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

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

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

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

    Hi Pavel,

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

    Cheers,

    Li

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

      Thank you for feedback.

      @ But the computing slows down considerably

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

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

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

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

    Hi Pavel,

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

    However, I have bumped into one problem

    When trying to compile


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

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

    I’m getting error (gcc 4.4.3)

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

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

    Is it a known limitation? Can

    #include <unsupported/Eigen/MPRealSupport>

    be updated to support cwise?

    Thanks a lot!
    Jirka

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

    Hi Pavel,

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

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

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

    Thanks
    Jirka

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

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

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

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

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

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

        Yes, ARPREC is definitely behind MPFR.

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

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

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

        Thanks
        Jirka

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

          This might be helpful: An implementation of PSLQ in GMP

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

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

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

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

            Hi Pavel,

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

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

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

            Jirka

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

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

    Thanks for response.

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

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

      Hi Jauhien,

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

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

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

    Pavel,

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

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

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

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

    Thanks for hard work.

    regards,
    Mark Eggleston

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

      Mark,

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

      As for std::complex<mpreal> – I do not recommend using it as it is. Although it is intended to be invariant of real scalar – yet functions are implemented using usual double precision constants here and there. Which results in lower overall precision of the result. Last time I checked MSVC’s code forstd::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 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值