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:

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

Obviously to write mathematical expressions in such cryptic form requires some time, practice and can be error prone for complex formulas. Moreover in order to use MPFR library existing software should be completely rewritten!

C++ wrapper for MPFR aims to alleviate these issues. It introduces new C++ type for high precision floating point numbers – `mpreal`

, which encapsulates low level `mpfr_t`

. All arithmetic and boolean operators (`+, -, *, /, >, !=,`

etc.) are implemented for `mpreal`

numbers through operator overloading technique. Mathematical functions (`sqrt, pow, sin, cos,`

etc.) are supported too. This makes possible to use MPFR calculations in the same simple way as calculations with numbers of built-in types `double`

or `float`

.

MPFR C++ version of the Schwefel function is:

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

## Features

Main MPFR C++ features are:

**MPFR C++ is constantly updated and improved**to be up to date with the ongoing development of MPFR library. We support latest MPFR 3.1.1 as well as its trunk version from SVN. (Author uses MPFR C++ on a daily basis, which keeps improvements and updates coming)-
**MPFR C++ allows usage of human-friendly notation for mathematical expressions.**For example, to write`z = x + y`

instead of`mpfr_add(z,x,y,…)`

. All arithmetic and Boolean operators along with standard mathematical functions are supported. Precision and rounding mode can be easily controlled too. **MPFR C++ is simple to use – it is one-header library.**Just include`mpreal.h`

to you code and use`mpreal`

numbers the same way you usually use`double`

or`float`

ones. Example is included in distribution. MPFR C++ is the only C++ wrapper which natively supports**GNU GCC**and**Microsoft Visual C++**.**MPFR C++ allows painless porting from built-in types to MPFR**with minimal altering of already typed and tested mathematical expressions. In most cases only renaming of types is needed (e.g.`double`

->`mpreal`

).**MPFR C++ provides high performance interface for plain MPFR.**Most operations are designed to be inline which means native MPFR function is called directly without C++ overhead. In contrast to other wrappers MPFR C++ doesn’t use advanced C++ features like function objects, virtual functions, etc. because of significant decrease of speed they suffer.**MPFR C++ keeps correct accuracy of intermediate calculations**during complex expression evaluation in order to obtain precise final result. Other C++ wrappers use different strategies on handling intermediate calculations which could lead to significant accuracy decreasing of final result (see details in Internals section).

## License

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

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

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

## Download

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

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

In order to use MPFR C++ – just include `mpreal.h`

to you code and use `mpreal`

numbers as usual floating-point numbers of `double`

or `float`

types. See example in distribution for more information.

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

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

- MPFR-MPIR-x86-x64-MSVC2010.zip (4.5MB). Visual C++ 2010 binaries for MPFR 3.0.1 and MPIR 2.3.0

## Software using MPFR C++

Multiprecision Computing Toolbox **allows existing MATLAB programs to run in arbitrary precision – with little to no modifications to the source code**.

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

- Classes for Physics and Mathematics by Ulrich Mutze.
- Eigen C++ template library for linear algebra: vectors, matrices, and related algorithms. Use additional header file from Eigen distribution:
`#include <unsupported/Eigen/MPRealSupport>`

. - The Template Numerical Toolkit (TNT) is a collection of interfaces and reference implementations of numerical objects useful for scientific computing in C++.
- Exact Random Distributions by Charles Karney.

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:

- MPFR C++ has been included in MBLAS and MLAPACK.

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.

## 240 Comments

#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

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

#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

#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!

#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

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

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

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

#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??

#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?#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!

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

#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 ).

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

#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

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

#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

#Thanks for sharing the solution!

#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 …

generates the error, while this

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.

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

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

#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

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.

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

Please check this great site for explanation:

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.11

#Dear Pavel,

thank you very much!

All the best,

Daniel.

#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!

#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!

#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

#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

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

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

#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

#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

#Pavel

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

The package is very nice

Many thanks

#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

#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();

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

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

#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?

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

#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

alwaystruncate 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!

#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`

):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: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.

#When viewing this:

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:

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

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″)…

#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?

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

#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

……

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

#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?

#Hello Igor,

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

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

`MPREALSUPPORT_H`

somewhere else?#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

mprealwhich contains all files of MPFR C++, includingmpreal.o,dlmalloc.oandmpreal_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.cppandb.cppa.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

$

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

#Thank you very much for the link and the advice about

inlinekeyword! 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 asinline. So I think it would be correct to follow this rule in your header file too.#Yes, you are right.

I’ve included this fix in

`mpreah_eigen.h`

#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)

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

#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`

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

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

#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′|

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

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

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

#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).

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

#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 commandsvn co https://mpfrcpp.svn.sourceforge.net/svnroot/mpfrcpp/trunk [your-path]

will install the entire source tree in

your-path.#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> ^

#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<''

#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?

#With no link-time errors

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

#Update: If I change this:

inline template <>

to this

template <> inline

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

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

#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

#@”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).#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`

#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

#Ok, I’ll contact Eigen developers for answers.

#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++” ?

#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!

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

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

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

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

Then conversion works nicely:

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:#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.

#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-performanceSomething wrong with the world, C++ is slower than Java/Python…..

#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;

}

#@”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)`

.#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;

}

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

#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

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

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

#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

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

#Isaia,

Boost developers maintain their own wrapper for

`mpreal`

to make it more “Boost” friendly:http://www.boost.org/doc/libs/1_46_0/libs/math/doc/sf_and_dist/html/math_toolkit/using_udt/use_mpfr.html

As for me this problem seems to appear because of

`mpreal`

variable is declared somewhere in global scope.#I have the same problem. So do you have any hint on how to fix this.

#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+0×35) [0x7fe2fa683d05]

[ 2] /lib/x86_64-linux-gnu/libc.so.6(abort+0×186) [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+0×288) [0x7fe2b500e598]

[ 7] …_transfer_matrix.so(_ZN2Py11PythonClassIN15transfer_matrix12OpticalLayerEE21extension_object_initEP7_objectS5_S5_+0x18e) [0x7fe2b501410e]

[ 8] /usr/bin/python() [0x48928d]

[ 9] /usr/bin/python(PyObject_Call+0×44) [0x45d864]

[10] /usr/bin/python(PyEval_EvalFrameEx+0x9be) [0x496c4e]

[11] /usr/bin/python(PyEval_EvalCodeEx+0×145) [0x49d325]

[12] /usr/bin/python(PyEval_EvalFrameEx+0×802) [0x496a92]

[13] /usr/bin/python(PyEval_EvalCodeEx+0×145) [0x49d325]

[14] /usr/bin/python(PyEval_EvalFrameEx+0×802) [0x496a92]

[15] /usr/bin/python(PyEval_EvalCodeEx+0×145) [0x49d325]

[16] /usr/bin/python(PyEval_EvalCode+0×32) [0x4ecb02]

[17] /usr/bin/python() [0x4fdc74]

[18] /usr/bin/python(PyRun_FileExFlags+0×90) [0x42c182]

[19] /usr/bin/python() [0x4288a0]

[20] /usr/bin/python(PyEval_EvalFrameEx+0x42be) [0x49a54e]

[21] /usr/bin/python(PyEval_EvalCodeEx+0×145) [0x49d325]

[22] /usr/bin/python(PyEval_EvalFrameEx+0×802) [0x496a92]

[23] /usr/bin/python(PyEval_EvalCodeEx+0×145) [0x49d325]

[24] /usr/bin/python(PyEval_EvalFrameEx+0×802) [0x496a92]

[25] /usr/bin/python(PyEval_EvalCodeEx+0×145) [0x49d325]

[26] /usr/bin/python(PyEval_EvalFrameEx+0×802) [0x496a92]

[27] /usr/bin/python(PyEval_EvalCodeEx+0×145) [0x49d325]

[28] /usr/bin/python(PyEval_EvalCode+0×32) [0x4ecb02]

[29] /usr/bin/python(PyEval_EvalFrameEx+0x34d0) [0x499760]

*** End of error message ***

Aborted

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

#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

#main()

{

mpfr::mpreal::set_default_prec(...); // set precision at the beginning of the thread

// do all calculations after

...

}

#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

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

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

#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

#Fixed. BTW what happens if you activate int64?

#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

#Hilarious output!

What is version of gcc you have?

#Its gcc-4.4.5

I can try on another machine…

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

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

#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.#sizeof(int64_t) = 8

sizeof(long int) = 8

sizeof(unsigned long int) = 8

sizeof(unsigned long int) = 8

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

Sorry to bug you with so many questions.

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

yes, these are x64 machines/systems.

#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!

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

#Actually I think I found solution – could you try latest version from the rep?

Now it handles GCC better.

#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

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

#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

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

#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

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

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

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

#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?

#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

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

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

Thanks!

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

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

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

#Yes, works now~ Thanks!

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

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

#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

#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.#Spelling error i think:

s/Doug Lee/Doug Lea/

#Yes, you are right, thanks.

#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

#`cwise()`

is removed from Eigen3. Read this link: http://eigen.tuxfamily.org/dox-devel/Eigen2ToEigen3.html#CoefficientWiseOperationsIn short, you could do this using one of the ways:

y.array().abs().minCoeff();

y.cwiseAbs().minCoeff();

#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

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

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

#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

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

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

#Thanks for answer.

Project is free, so I’ll use it under LGPL, how is stated in source files.

I will use revision date from repository for version number then.

And thanks for library. )

#May be it can be interesting for you: mpfrc++ is available in gentoo sunrise overlay now: http://git.overlays.gentoo.org/gitweb/?p=proj/sunrise-reviewed.git;a=tree;f=dev-cpp/mpfrc%2B%2B

#Of cause it is very interesting! Thank you!

#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

#Mark,

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

As for

`std::complex<mpreal>`

– I do not recommend using it as it is. Although it is intended to be invariant of real scalar – yet functions are implemented using usual`double`

precision constants here and there. Which results in lower overall precision of the result. Last time I checked MSVC’s code for`std::complex`

I found it unacceptable for serious calculations with guaranteed accuracy. Check carefully functions code before using it.Same goes for boost – many special functions are implemented using few terms of series/fractions approximation with

`double`

precision constants to put aside that many such algorithms are not applicable for arbitrary precision computing at all.@

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

#Pavel,

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

#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

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

#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

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

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

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

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

#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

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

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

#I did try with higher precision. It still initialized the mpfr to a wrong value. I mean, the representation achieved with mpreal was much less precise than double representation. The parameter I am evaluating is the debug value shown – might not be the best,but, does facilitate for me, since comparing real numbers is much more natural for most common human, like I, hehehe.

The use I intend for mpreal is the following:

An interpreter uses double as interface. But the calculations that follows the interpreter are much sensitive, so I wanted to use a better precision representation, that allowed me to do better math. And then convert back to double the obtained results to proceed to integration numeric integration.

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

Paulo Sherring.

#Hi Paulo,

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

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

#For some unknown reason, I was getting – from time to time – this bizarre conversions. In the end, I found out that using MP was not for real time applications such as my, since it the code execution time became much longer than with regular FP, something I could not afford.

I will keep experimenting with your MPFR C++.

And thanks for all the fish!

#Hi Pavel,

I’m looking for a way to do calculations with non-integer numbers that would *always* yield the same results, even with other compilers, other architectures etc. You cannot achieve this by using floats or doubles, so I’m trying to find a library that lets you do that, even if I need to lose a little bit of performance. The high precision of the results is not really important for me, the result should just always and everywhere be the same.

Is mpfr (hence mpfrc++) a good solution for what I’m looking for? According to “with correct rounding” from the GNU MPFR description, it seems like it is, but I would like to be sure before I change all my code to use mpreal…

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

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

Thank you in advance.

#Dear Pavel,

BOOST announced a couple of versions ago that they have included support for

mpreal. (Great news!)Has this support been maintained? On version 1.48.0, I am trying to use the binding for

mpreal, but get “ambiguous overload” compile errors for various operators.Is only an older version of

mprealsupported? Ismprealonly supported for older version of BOOST ?Thank you! and great wrapper!

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

#Hi Pavel

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

mpreal& mpreal::operator=(const char* s)

{

mpfr_t t;

#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)

set_custom_malloc();

#endif

mpfr_init2(t, mpfr_get_prec(mp));

if(mpfr_set_str(t, s, default_base, default_rnd) == 0)

{

mpfr_set(mp, t, mpreal::default_rnd);

mpfr_clear(t);

MPREAL_MSVC_DEBUGVIEW_CODE;

}else{

mpfr_clear(t);

}

return *this;

}

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

mpreal& mpreal::operator=(const std::string& s)

{

mpfr_t t;

#if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)

set_custom_malloc();

#endif

mpfr_init2(t, mpfr_get_prec(mp));

if(mpfr_set_str(t, s.c_str(), default_base, default_rnd) == 0)

{

mpfr_set(mp, t, mpreal::default_rnd);

mpfr_clear(t);

MPREAL_MSVC_DEBUGVIEW_CODE;

}else{

mpfr_clear(t);

}

return *this;

}

Best regards,

John

#Dear John,

Thank you very much for your contribution!

Meanwhile I have re-designed mpreal to be one-header library, with many other bug fixes and improvements.

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

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

Today I have released new version, which includes major improvements and bug fixes., fixed bugs among other things.

I’ve modified it to be thread-safe, removed static variables to escape “hell of unpredictable order of global variables initialization” ,

added specialization for std::numeric_limits

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

API compatibility with older versions should be preserved.

I would appreciate tests, comments, suggestions.

#Hey Pavel,

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

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

@misc{mpfrcpp,

author = {P. Holoborodko},

title = {MPFR C++},

howpublished = {http://www.holoborodko.com/pavel/mpfr/}

year = {2008-2012}

}

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

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

#Hi Pavel,

I would like to format the output from my program using std::ios_base::precision and std::ios_base::setf.

When using mpreal the first one works, but instead of counting the precision as the number of digits after the dot (as it does for a double), it counts all the digits, including those before the dot.

The second one instead doesn’t work at all.

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

#include <fstream

#include "mpreal.h"

using namespace mpfr;

using namespace std;

int main()

{

mpreal::set_default_prec(128);

ofstream out;

double h[5];

mpreal m[5];

out.precision(15);

out.setf(ios::scientific,ios::floatfield);

out.open("output");

for (int i = 0; i < 3; i++)

{

h[i] = 100. / (i+7);

m[i] = 100. / (i+7);

}

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

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

`out.close();`

return 0;

}

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

1.428571428571429e+01 1.250000000000000e+01 1.111111111111111e+01

14.2857142857143 12.5 11.1111111111111

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

Thank you for the fantastic wrapper!

#Hi,

Currently MPFR C++ doesn’t support

`std::ios_base::setf`

– will include this in next version.Now you can use

`toString(format)`

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

#General format specification is:

`"%[[width].[precision]]RN[e,f,g]"`

. In your case format might look like:`"%RNe"`

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

#thanks Pavel.

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

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

inline mpreal::mpreal(const long long int u, mp_prec_t prec, mp_rnd_t mode)

{

mpfr_init2(mp,prec);

mpfr_set_si(mp, u, mode);

MPREAL_MSVC_DEBUGVIEW_CODE;

}

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

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

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

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

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

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

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

#Functions “mpfr_set_ui/si” should be fine.

Basically constructor for “long long int” should be equivalent to “long int” one.

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

#[quote]Functions “mpfr_set_ui/si” should be fine.

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

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

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

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

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

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

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

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

Then move from x32 to x64 would be painless.

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

There is some macro-logic in mpreal.h which tries to make things smooth:

(a) for x32 builds we define additional constructors for int64_t (aka “long long int” or “intmax_t” )

(b) for x64 builds we remove constructors for such type since “long int” is already 64bit wide.

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

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

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

#How is the following code compiled?

bool test = mpreal("1.0001") > 1

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

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

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

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

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

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

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

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

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

Thank you in advance for help

Dariusz

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

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

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

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

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

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

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

mpreal_max is not a member of mpfr

This error comes from the lowest and highest functions defined in the MPRealSupport file. I tried to use the mpreal_max function with the mpreal.h header file

and I get a similar error – it appears that this function doesn’t exist. If I get rid of this function in the MPRealSupport file then the sample code provided by Eigen runs without problem.

Any thoughts on this?

thanks

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

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

1>R:\sdks\boost\boost_1_53_0\boost/math/bindings/mpreal.hpp(299): error C2593: ‘operator *’ is ambiguous

1> R:\sdks\boost\boost_1_53_0\boost/math/bindings/mpreal.hpp(47): could be ‘mpfr::mpreal mpfr::operator *(const mpfr::mpreal &,const T &)’ [found using argument-dependent lookup]

1> with

1> [

1> T=int

1> ]

1> R:\sdks\mpfr_mpir\mpfr_mpir_x86_x64_msvc2010\current\mpfrcpp\mpreal.h(734): or ‘const mpfr::internal::result_type::type mpfr::operator *(const mpfr::mpreal &,const Rhs &)’ [found using argument-dependent lookup]

1> with

1> [

1> Rhs=int

1> ]

1> while trying to match the argument list ‘(mpfr::mpreal, int)’

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

#Hi Pavel,

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

//#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))

//

// // Use MPFR native function for output

// char format[128];

// int digits;

//

// digits = n > 0 ? n : bits2digits(mpfr_get_prec(mp));

//

// sprintf_s(format,”%%.%dRNg”,digits); // Default format

//

// return toString(std::string(format));

//

//#else

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

Thanks in advance.

#Hello Pavel, I am reporting an error I encountered in reading formatted inputs when switching type from double to mpreal.

Specifically, if there is a comma after a number instead of a space, the c_str() call in “inline std::istream& operator>>(std::istream &is, mpreal& v)” causes an “Assertion Failed” runtime error.

A program demostrating the problem can be found in the first post at http://ubuntuforums.org/showthread.php?t=2160022

Nothing major, of course, but I think it is worth reporting since the change of type causes unexpected errors in an otherwise working code.

Thanks for the awesome wrapper!

#Hello Dirich,

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

#I am having trouble getting mpreal to compile using vc++ 2005. Are there step by step instructions somewhere? Here is what I tried:

1. downloaded the zips suggested on this page

2. added the folders to my include directories listing

3. in code, used #include “mpreal.h”

4. used the following code:

using mpfr::mpreal;

mpreal number;

number = “5″;

5. Got the following error:

error LNK2019: unresolved external symbol _mpfr_get_default_rounding_mode referenced in function “public: static enum mpfr_rnd_t __cdecl mpfr::mpreal::get_default_rnd(void)” (?get_default_rnd@mpreal@mpfr@@SA?AW4mpfr_rnd_t@@XZ)

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

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

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

mpreal.h: In function ‘int mpfr::sgn(const mpfr::mpreal&)’:

mpreal.h:1854: error: ‘mpfr_signbit’ was not declared in this scope

mpreal.h: In member function ‘mpfr::mpreal& mpfr::mpreal::setSign(int, mpfr_rnd_t)’:

mpreal.h:1860: error: ‘mpfr_setsign’ was not declared in this scope

mpreal.h: In function ‘const mpfr::mpreal mpfr::besselj0(const mpfr::mpreal&, mpfr_rnd_t)’:

mpreal.h:2159: error: ‘mpfr_j0’ was not declared in this scope

mpreal.h: In function ‘const mpfr::mpreal mpfr::besselj1(const mpfr::mpreal&, mpfr_rnd_t)’:

mpreal.h:2160: error: ‘mpfr_j1’ was not declared in this scope

mpreal.h: In function ‘const mpfr::mpreal mpfr::bessely0(const mpfr::mpreal&, mpfr_rnd_t)’:

mpreal.h:2161: error: ‘mpfr_y0’ was not declared in this scope

mpreal.h: In function ‘const mpfr::mpreal mpfr::bessely1(const mpfr::mpreal&, mpfr_rnd_t)’:

mpreal.h:2162: error: ‘mpfr_y1’ was not declared in this scope

mpreal.h: In function ‘const mpfr::mpreal mpfr::remainder(const mpfr::mpreal&, const mpfr::mpreal&, mpfr_rnd_t)’:

mpreal.h:2181: error: ‘mpfr_remainder’ was not declared in this scope

mpreal.h: In function ‘const mpfr::mpreal mpfr::remquo(long int*, const mpfr::mpreal&, const mpfr::mpreal&, mpfr_rnd_t)’:

mpreal.h:2188: error: ‘mpfr_remquo’ was not declared in this scope

mpreal.h: In function ‘const mpfr::mpreal mpfr::lgamma(const mpfr::mpreal&, int*, mpfr_rnd_t)’:

mpreal.h:2205: error: ‘mpfr_lgamma’ was not declared in this scope

mpreal.h:2206: error: ‘mpfr_lgamma’ was not declared in this scope

mpreal.h: In function ‘const mpfr::mpreal mpfr::besseljn(long int, const mpfr::mpreal&, mpfr_rnd_t)’:

mpreal.h:2215: error: ‘mpfr_jn’ was not declared in this scope

mpreal.h: In function ‘const mpfr::mpreal mpfr::besselyn(long int, const mpfr::mpreal&, mpfr_rnd_t)’:

mpreal.h:2222: error: ‘mpfr_yn’ was not declared in this scope

mpreal.h: In function ‘const mpfr::mpreal mpfr::fms(const mpfr::mpreal&, const mpfr::mpreal&, const mpfr::mpreal&, mpfr_rnd_t)’:

mpreal.h:2252: error: ‘mpfr_fms’ was not declared in this scop

#include

#include “mpreal.h”

using namespace mpfr;

using namespace std;

mpreal N011(mpreal VA1, mpreal VA2)

{

mpreal N01;

N01 = sqrt(-2*log(1-VA1))*cos(2*const_pi()*VA2);

return N01;

}

int main()

{

mpreal::set_default_prec(1024);

cout.precision(50);

cout << N011(0.2, 0.3) << endl;

return 0;

}

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

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

#it works now , I forgot the dynamic linking.

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

test_test.cpp

#include

#include

#include

using namespace mpfr;

using namespace Eigen;

int main()

{

// set precision to 256 bits (double has only 53 bits)

mpreal::set_default_prec(256);

// Declare matrix and vector types with multi-precision scalar type

typedef Matrix MatrixXmp;

typedef Matrix VectorXmp;

MatrixXmp A = MatrixXmp::Random(100,100);

VectorXmp b = VectorXmp::Random(100);

// Solve Ax=b using LU

VectorXmp x = A.lu().solve(b);

std::cout << "relative error: " << (A*x – b).norm() / b.norm() << std::endl;

return 0;

}

~

~

In file included from test_test.cpp:2:

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:33:20: error: mpreal.h: No such file or directory

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:114:38: error: missing binary operator before token "("

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:80: error: ‘mpfr’ was not declared in this scope

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:80: error: template argument 1 is invalid

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:81: error: ‘mpfr’ was not declared in this scope

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:81: error: template argument 1 is invalid

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:112: error: ‘mpfr’ has not been declared

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:112: error: expected constructor, destructor, or type conversion before ‘random’

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:131: error: ‘mpfr’ has not been declared

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:131: error: expected constructor, destructor, or type conversion before ‘random’

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:136: error: expected ‘,’ or ‘…’ before ‘::’ token

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:136: error: ISO C++ forbids declaration of ‘mpfr’ with no type

/home1/02084/zzwtgts/include/Eigen/MPRealSupport: In function ‘bool Eigen::internal::isMuchSmallerThan(int)’:

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:138: error: ‘mpfr’ is not a class or namespace

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:138: error: ‘a’ was not declared in this scope

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:138: error: ‘mpfr’ is not a class or namespace

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:138: error: ‘b’ was not declared in this scope

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:138: error: ‘prec’ was not declared in this scope

/home1/02084/zzwtgts/include/Eigen/MPRealSupport: At global scope:

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:141: error: expected ‘,’ or ‘…’ before ‘::’ token

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:141: error: ISO C++ forbids declaration of ‘mpfr’ with no type

/home1/02084/zzwtgts/include/Eigen/MPRealSupport: In function ‘bool Eigen::internal::isApprox(int)’:

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘mpfr’ is not a class or namespace

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘a’ was not declared in this scope

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘b’ was not declared in this scope

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘mpfr’ is not a class or namespace

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘mpfr’ is not a class or namespace

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘mpfr’ is not a class or namespace

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:143: error: ‘prec’ was not declared in this scope

/home1/02084/zzwtgts/include/Eigen/MPRealSupport: At global scope:

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:146: error: expected ‘,’ or ‘…’ before ‘::’ token

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:146: error: ISO C++ forbids declaration of ‘mpfr’ with no type

/home1/02084/zzwtgts/include/Eigen/MPRealSupport: In function ‘bool Eigen::internal::isApproxOrLessThan(int)’:

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:148: error: ‘a’ was not declared in this scope

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:148: error: ‘b’ was not declared in this scope

/home1/02084/zzwtgts/include/Eigen/MPRealSupport:148: error: ‘prec’ was not declared in this scope

test_test.cpp: At global scope:

test_test.cpp:4: error: ‘mpfr’ is not a namespace-name

test_test.cpp:4: error: expected namespace-name before ‘;’ token

test_test.cpp: In function ‘int main()’:

test_test.cpp:9: error: ‘mpreal’ has not been declared

test_test.cpp:11: error: ‘mpreal’ was not declared in this scope

test_test.cpp:11: error: template argument 1 is invalid

test_test.cpp:11: error: invalid type in declaration before ‘;’ token

test_test.cpp:12: error: ‘mpreal’ cannot appear in a constant-expression

test_test.cpp:12: error: template argument 1 is invalid

test_test.cpp:12: error: invalid type in declaration before ‘;’ token

test_test.cpp:13: error: ‘MatrixXmp’ is not a class or namespace

test_test.cpp:14: error: ‘VectorXmp’ is not a class or namespace

test_test.cpp:16: error: request for member ‘lu’ in ‘A’, which is of non-class type ‘main::MatrixXmp’

test_test.cpp:17: error: request for member ‘norm’ in ‘((A * x) – b)’, which is of non-class type ‘int’

test_test.cpp:17: error: request for member ‘norm’ in ‘b’, which is of non-class type ‘main::VectorXmp’

#mpfr-3.1.2, the latest version

#dear,

can I/we have a c++ header for multiprecision integers only.I have tried the real version ,..it works with my c++ routines for clipping(only 50X slow down).I want to try out a integer only library available on the net which has its own 64 bit integer manipulation routines.

I expect it as easy to use as mpreal….just substitute double by mpreal and the program compiled without further effort.

Mahesh Naik

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

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

#Dear Pavel:

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

1. Installing MPFR and GMP libraries.

2. Using MPFR C++ interface (mpreal.h, mpreal.cpp) along with header file mpreal_eigen.h

3. Using mpreal type (provided by MPFR C++) instead of built-in type double or float.

But I also found head file #include in this module

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

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

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

In file included from test_test.cpp:3:

mpreal_eigen.h:51: error: expected unqualified-id before ‘<’ token

mpreal_eigen.h:56: error: expected ‘;’ before ‘inline’

mpreal_eigen.h:61: error: expected unqualified-id before ‘<’ token

test_test.cpp:15: error: expected ‘;’ at end of input

test_test.cpp:15: error: expected ‘}’ at end of input

my test_tes.cpp file is very simple:

#include

#include “mpreal.h”

#include “mpreal_eigen.h”

using namespace mpfr;

using namespace Eigen;

int main()

{

mpreal::set_default_prec(256);

typedef Matrix MatrixXmp;

MatrixXmp A = MatrixXmp::Random(100,100);

std::cout << "relative error: " << A << std::endl;

return 0;

}

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

#Dear Justin,

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

Please use

`#include <unsupported/Eigen/MPRealSupport>`

as described above on the page.#I am quite new to both mpfr and mpreal, so maybe I just haven’t read the manual thoroughly enough ..

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

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

#define get_mandel_value(dst,src) { FLOAT_TYPE dst_tmp(src.val); dst = dst_tmp; }

#define set_mandel_value(dst,src) strncpy(dst.val,src.toString("%.128RNe").c_str(),mpfr_buff_size - 16)

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

I would like to do something like this:

#define get_mandel_value(dst,src) \

{ \

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

}

`#define set_mandel_value(dst,src) \`

{ \

mpfr_exp_t *expptr = new mpfr_exp_t(); \

memset(dst.val,0,mpfr_buff_size); \

if ( mpfr_get_str(dst.val,expptr,mpfr_str_base,mpfr_buff_size-16,src.mpfr_ptr(),MPFR_RNDN) == NULL ) { printf("set_mandel_value failed!\n"); exit(1); }\

delete expptr; \

}

As you can see, I am calculating Mandelbrot I have a FLOAT_TYPE which can be either a long double or a mpreal float.

Also, I am a bit confused over the expptr, why is it necessary.

I have tried different format strings – maybe I didn’t hit the correct combination?

I have used mpfr_set_default_prec(1024) and even 8192 – no change.

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

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

#Update1 : It seems, that I hit the precision of the “double” data type.

Somewhere along the way it is converted to a double.

Update2 : I have also tried dst = src.val in the first version of get_mandel_value, so no temporary variable is needed. No change in precision, however.

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

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

#Using the strings is the official way.

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

Btw, you don’t need to allocate expptr in heap every time. Just define expptr as variable and pass &expptr to mpfr_get_str.

Stack allocations are much faster then heap.

#Thank you for the reply. Everything works now, I read the manual some more (and also the mpreal.h include file).

I am calculating Mandelbrot (don’t ask why) using any available CPU resource on the network. So I need to send a set of coordinates to any machine (32 or 64 bit), and the bottleneck is CPU time, not the network, so I can live with long strings.

I looked in mpreal.h and found, that I didn’t need to access any mpfr internals directly. I can use the mpreal functions, which beautifully wrap up all the mpfr internals for me The mpreal internals stores bits in limbs, which most likely are 32/64 bit dependent, so I can’t use any access to them – I need it in a normalized format, and it seems that strings are the only good way to do that.

I want to be able to switch between normal long double floating point numbers and mpreals – and it is easily done, all that is needed is a way of transporting the numbers using the S_MANDEL_FLOAT structure.

I was audacios enough to make some timings on a zoom somewhere in the Mandelbrot image:

// single threaded @ 1.2 GHz:

// SD -> 233M (double)

// LD -> 220M (long double)

// 64 -> 758K (mpfr with 64 bits)

// 256 -> 672K

// 512 -> 544K

// 1024 -> 340K

// 2048 -> 202K

// 4096 -> 94K

That is, a 2048 bit mpreal is approximately 1000 times slower than a long double, but a 256 bit mpreal is more than 3 times faster than a 2048 mpreal. I know that it is impossible to make proper floating point benchmarks, because computing time depends on the input number(s), so other people may get other results when testing.

I ended up with the following header file (note that mpfr_buff_size may be too large, but when experimenting with very large number of bits, then it can easily get too small):

#include "mpreal.h"

using mpfr::mpreal;

#define FAST 1#define FLOAT_PREC 256

#if FAST == 0#define mpfr_buff_size 16384

#define mpfr_str_base 10

#pragma pack(push,1)

typedef struct

{

char val[mpfr_buff_size];

} S_MANDEL_FLOAT;

#pragma pack(pop)

#define FLOAT_TYPE mpreal

#define F2LD(val) val.toLDouble()

#define

get_mandel_value(dst,src)dst = src.val;#define

set_mandel_value(dst,src)\strncpy(dst.val,src.toString(0,mpfr_str_base,MPFR_RNDN).c_str(),mpfr_buff_size - 16);

#else#define FLOAT_TYPE long double

#define F2LD(val) (long double)val

#pragma pack(push,1)

typedef struct

{

FLOAT_TYPE value;

} S_MANDEL_FLOAT;

#pragma pack(pop)

#define

get_mandel_value(dst,src)dst = src.value#define

set_mandel_value(dst,src)dst.value = src#endif#Comparison and code looks good.

To make things shorter you might use simplified version with default parameters:

`src.toString().c_str()`

.***

I have routines for mpreal serialization to bitstream (to avoid string conversion) based on mpfr_t internal raw buffers.

However it suffers from being dependent on limb size and it is based on undocumented MPFR features subject to change anytime.

Inclusion of universal serializers into MPFR itself has been discussed for years among developers. You might find some draft routines in trunk branch in SVN. However it is not critical for your application as I see.

***

Anyway, thank you for your work and please keep me updated on your experience with mpreal.

#Dear Pavel,

thank you for sharing your code with us.

I have to use the exponential function with a negative argument. It seems that the identity

,

although mathematically correct, it has numerical evaluation problems when . For example please try: cout << exp( float_precision(-1.7E2) ) << endl;

The result is incorrect.

Using the standard c math library, the results is correct, i.e., cout << exp( -1.7E2 ) <<endl;.

I would much appreciate if you check the problem and let me know how the above problem can be corrected.

Thanks and best regards,

Nikos

#I see no such problem:

/* use 30 digits precision */

int digits = mpfr::digits2bits(30);

mpfr::mpreal::set_default_prec(digits);

mpfr::mpreal x("-1.7e2");

std::cout.precision(20);

std::cout < < exp(x) << std::endl;

std::cout << exp(x.toDouble()) << std::endl;

Output:

1.4788975056432133844e-74 < -- mpreal

1.4788975056432133e-074

#Thank you for your prompt response!

I am using Visual Studio C++ 2010 binaries for MPFR 3.0.1 and MPIR 2.3.0 given as a zip file in the “Download” section of the current page. So, I only use in my VS2010 project the 4 header and 1 cpp files provided therein. The header I use in my project to conduct floating-point calculations is: #include “fprecision.h”. Thus, I cannot compile your code.

Are there any equivalent commands for my case to adjust the accuracy according to your previous post? Or, do I have to include some more libraries?

Thanks once again,

Nikos

#I have no idea what is “fprecision.h”.

You need to include only one file – “mpreal.h” (and install mpfr/mpir as you did already).

#Dear Pavel,

thank you so much for your help!

Following your suggestions I managed to correctly evaluate the exponential function with any negative argument.

Best,

Nikos

PS: The header “fprecision.h” mentioned above has nothing to do with the MPFR project. Sorry for any misunderstanding caused.

#One final question.

How is it possible to change the number of bits that is used to perform floating-point arithmetic?

I tried your above lines

/* use 30 digits precision */

int digits = mpfr::digits2bits(30);

mpfr::mpreal::set_default_prec(digits);

mpfr::mpreal x("-1.7e2");

`cout<< sizeof(x) << endl;`

Using any number instead of 30, the sizeof function always returns 24 as the output. So, I cannot change the mpfr::mpreal numbers accuracy.

Can you please give some advise?

Thanks,

Nikos

#Size of “mpreal” has no relation to precision.

Number is stored in heap memory, “mpreal” has only pointers to its data – that is why sizeof(mpreal) is always the same.

Use machine epsilon to check the actual accuracy of a precision / number:

std::cout < < mpfr::machine_epsilon(128) << std::endl;

std::cout << mpfr::machine_epsilon(x) << std::endl;

Use

`getPrecision()/setPrecision()`

to get the precision of a number.#Dear Pavel,

first of all, I would like to say that MPFR is a great library and helps me a lot. I am not the biggest expert in using MPFR so I do not know what this error means:

sub1sp.c:658: assertion failed: bbcp != (mp_limb_t) -1

I appears in the middle of a big loop where many very small values are computed and used.

Can you please give some advise?

Have a nice Christmas!

Thank you very much!

Florian

#Dear Pavel,

first of all, thank you for your work and your package.

I have a question about an error I get when I am running a program using MPFR:

sub1sp.c:658: assertion failed: bbcp != (mp_limb_t) -1

The program uses and computes a lot of very small values.

Could you help me, please?

Thank you,

Florian

#Sorry for the double posting before

#Recently I installed the ‘Ubuntu package for MPFR C++’ an my aged laptop computer and was completely surprised that replacing type double by mpreal caused no noticible increase in computation time for precisions till incredible 256 decimal digits. Similar tests two years ago saw computations slowed down by a factor of ~100. Unbelievable progress, congratulations !!!!

#Thank you very much for your comment!

Indeed performance has been the main priority all this time. Many knowledgeable people contributed to the code (e.g. RVO), and technology moved further (e.g. move semantic). All combined gave significant boost for the speed.

I don’t know what version of MPFR/GMP you are using, but improvements there might contribute the most to the performance ;).

#Just to correct my previous premature and over-optimistic note. The observation about slowing down by a factor ~100 was from 2009 and thus not only two years ago. The observation that using mpreal instead of double did not increase computation time noticibly was brought about by a program that was very special in being graphical to a high degree. Graphics-related floating point computations are done in my C+- system always in double so that mpreal was involved only in a small part of the computation. For a less-graphical, ‘normal’ program I got: The factor by which prec n is slower than double was found to be 2.36 2.50 3.40 for n = 64, 128, 256 respectively. Also this is admirable progress and the congratulations need not be withdrawn in any way.

#I get the following error;

1>c:\davids\vcnet\mpfrc++-3.5.6\mpreal.h(2566): error C2665: ‘mpfr::grandom’ : none of the 2 overloads could convert all the argument types

from the code:

#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))

inline const mpreal grandom(unsigned int seed = 0)

{

static gmp_randstate_t state;

static bool isFirstTime = true;

if(isFirstTime)

{

gmp_randinit_default(state);

gmp_randseed_ui(state,0);

isFirstTime = false;

}

if(seed != 0) gmp_randseed_ui(state,seed);

return mpfr::grandom(state);

}

#endif

I am using visual studio 2013 and downloaded the files yesterday from your website

I have also had to comment out:

#define MPREAL_HAVE_INT64_SUPPORT

thank you

david

#Hi. I found your library very nice. I had written one but yours is much superior. Thanks for sharing it with the world.

I have a ticket to this code: when compiling with

`g++ -Wall -Wextra -Wfatal-errors`

, I get the warning:`mpreal.h:2402:102: warning: unused parameter 'r' [-Wunused-parameter]`

My understanding is that this is because the function

`inline const mpreal const_infinity (int sign = 1, mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd())`

is not using its last parameter, r.

Thus, it could have be re-written into

`inline const mpreal const_infinity (int sign = 1, mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t)`

if we want to keep backward compatibility and library systematic input of rounding parameter, or to

`inline const mpreal const_infinity (int sign = 1, mp_prec_t p = mpreal::get_default_prec())`

if we allow backward incompatibility.

Regards,

Jorge

#Hi Jorge. Thank you for your feedback.

I think it is better to just remove unused parameter. Compatibility will be preserved, since nobody was using the ‘r’ anyway :).

Will update repository shortly.

#Hi, Pavel,

Thank you very much for your library! I like it.

Do you know if we can pass a function pointer of type mpreal->mpreal to Boost’s optimization function templates, say, of this interface:

template class F, class T

std::pair T, T brent_find_minima(F f, T min, T max, int bits, boost::uintmax_t& max_iter) ?

I got this compilation error: “reference to overloaded function could not be resolved” when calling

boost::math::tools:: brent_find_minima(p_implm, begin, end, bits, iter);

in which p_implm is a user-defined simple function of type mpreal->mpreal.

The compilation error is in the screenshot

https://www.evernote.com/shard/s306/sh/e357903e-245c-4c7b-851f-86c331bc04f1/253e2ecbb100465d560a6c53183073d3

Note that the error points to policy.hpp of boost library. So I guess I made something wrong or maybe

mpreal is not designed to work the way as I naively thought.

What do you think?

#Hi Zhoulai,

The problem there is that constant “std::numeric_limits::digits” is undefined for “mpreal”.

Since “mpreal” can have variable number of digits (that is the point of the library) – “digits” is defined as function for the “mpreal”.

Please check the std::numericl_limits<mpreal> specialization at the end of mpreal.h.

The possible solution would be to add constant “std::numeric_limits<mpreal>::digits” with some dummy value – just so that boost would not complain anymore.

#Thank you for your clarification. Do you mean that I need to manually modify mpreal.h?

#In a few minutes I will release the updated version with special workaround for the problem.

Basically you will need to disable one macro in mpreal.h in order to have full compatibility with standard numeric_limits.

#It is already updated. See here:

https://bitbucket.org/advanpix/mpreal/

1. Comment out the following line:

#define MPREAL_HAVE_DYNAMIC_STD_NUMERIC_LIMITS

2. Do the proper modifications for “digits”, etc. at the end of mpreal.h file – so that it matches your precision.

#Hi Pavel.

Two other minor issues that the compiler warns:

line 2977 (of trunk)

`inline static int digits() { return mpfr::mpreal::get_default_prec(); }`

should read

`inline static int digits() { return (int)mpfr::mpreal::get_default_prec(); }`

Line 1883-1886

`inline int mpreal::getPrecision() const`

{

return mpfr_get_prec(mp);

}

should read

`inline int mpreal::getPrecision() const`

{

return (int)mpfr_get_prec(mp);

}

both of them are warnings about implicit conversion precision lost.

Regards,

Jorge

#Hi Jorge,

Thank you for your report. All warnings have been fixed along with other improvements released today. Please check the new version.

## One Trackback

[...] my concerns. But there is a tiny problem. MPFR is based on native C style. and its not so easy. MPFR++ is a C++ wrapper to the native MPFR. If you want to use this, you have to include the files with [...]