Math-MPFR

Perl interface to the MPFR (floating point) library


License
Artistic-1.0-Perl

Documentation

This module wraps the MPFR library functions.

The MPFR library is a C library for multiple-precision floating-point
computations with exact rounding (also called correct rounding). It
is based on the GMP multiple-precision C library.

The main goal of MPFR is to provide a library for multiple-precision
floating-point computation which is both efficient and has a
well-defined semantics. It copies the good ideas from the
ANSI/IEEE-754 standard for double-precision floating-point
arithmetic (53-bit mantissa).

It also offers a wide range of trig, log, and other functions, and
constants.

MPFR, like GMP, is free. It is distributed under the
GNU Lesser General Public License (GNU Lesser GPL).

Because this module wraps the MPFR functions, it requires that both
the GMP C library and the MPFR C library have been installed.

For the GMP library see:
https://gmplib.org

For the MPFR library see:
https://www.mpfr.org

Minimum required version of gmp is gmp-4.2.0.
Minimum required version of mpfr is mpfr-3.0.0.
You'll get errors if you try to build Math::MPFR against an
insufficiently recent version of the mpfr library.
Some features of Math::MPFR require later versions of the gmp and mpfr
libraries. If the versions are not sufficiently recent, then those
features will not be available.

To build this module you need perl 5.6.0 or later. I'm not sure of all
the requirements to get it to build with earlier versions of perl, but
it's definite that the XS code relating to operator overloading will
not compile with perl versions prior to 5.6.

Build in the usual way:

 perl Makefile.PL
 make
 make test
 make install
 make realclean (must be run before re-building.)

When building this module, the GMP and MPFR libraries will need to be
accessible. If those files are in a location where your compiler does
not find them by default, then instead of running 'perl Makefile.PL',
you'll need to run:

perl Makefile.pl INC="-I/path/to/gmp_includes -I/path/to/mpfr_includes"
 LIBS="-L/path/to/mpfr_lib -lmpfr -L/path/to/gmp_lib -lgmp"

Other commandline args you may want to provide to 'perl Makefile.PL' are
D64=1 (for _Decimal64 support), D128=1 (for _Decimal128 support) and
F128=1 (for __float128 support).
See the Decimal64/128 and Float128 sections (below).
There are also some commandline args that provide some debugging of nvtoa() and doubletoa().
See the Debug section below.

========
Checklib
========

During the running of the Makefile.PL a check is run to ensure that the
gmp and mpfr libraries can be found when needed.
This check can be skipped by:
a) providing CHECK=0 as a Makefile.PL commmand line argument
or
b) by uncommenting the line (about line 19) that begins with:
#$checklib = 0;

==================================
64-bit-int and long double support
==================================

If your perl's Config reports that 'ivsize' is greater than or
equal to 8 && 'ivtype' is not 'long', then Math::MPFR will, by default,
be built with access to the Rmpfr_*_uj and Rmpfr_*_sj functions. Else,
access to those functions is, by default, denied.

Similarly, if your perl's Config reports that 'nvsize' is greater than
8 then Math::MPFR will be built with access to the Rmpfr_*_ld functions.

I am contactable by email at sisyphus at(@) cpan dot (.) org.

===================================
Decimal64 and Decimal128 conversion
===================================

The functions Rmpfr_set_DECIMAL64 and Rmpfr_get_DECIMAL64 allow
conversion between Math::Decimal64 (_Decimal64) and Math::MPFR (mpfr_t)
objects.
For this feature to be available you firstly need a compiler that has
the _Decimal64 data type.
You'll also need to have a recent version of the mpfr library that has
been built with _Decimal64 support (ie that was configured with
'--enable-decimal-float').

This should all be detected and enabled automatically whenever these
conditions are met.

To utilise mpfr's _Decimal64 functionality you also need to install
Math::Decimal64.

If you wish you can avoid _Decimal64 support by providing D64=0 as an
argument to the Makefile.PL - ie run 'perl Makefile.PL D64=0';
You can ensure _Decimal64 support by providing the argument D64=1.

Note that forcing 'D64=1' will not work unless the conditions
mentioned earlier in this section are met.

The above holds true also for the Math::Decimal128 and the _Decimal128
type. Just replace all occurrences of "64" with "128".

=========================================================
Conversion between Math::Float128 and Math::MPFR objects
=========================================================

If 'perl -V:nvtype' reports __float128, see also the section
'Conversion between __float128 NV and Math::MPFR objects', below.
This section deals only with conversion between Math::Float128 and
Math::MPFR objects - and if your nvtype is __float128 there's
probably nothing to be gained by calling on Math::Float128.

The functions Rmpfr_set_FLOAT128 and Rmpfr_get_FLOAT128 allow
conversion between Math::Float128 (__float128) and Math::MPFR (mpfr_t)
objects.
For this feature to be available you firstly need a compiler that has
the __float128 data type.
You'll also need to have a recent version (4.0.0 or later) of the mpfr
library that has been built with __float128 support (ie that was
configured with'--enable-float128').

This should all be detected and enabled automatically whenever these
conditions are met.

To utilise mpfr's __float128 functionality in this way you also need
to install Math::Float128.

If you wish you can avoid Math::Float128 support by providing F128=0
as an argument to the Makefile.PL - ie run 'perl Makefile.PL F128=0';
You can ensure Math::Float128 support by providing the argument F128=1.

You can aternatively override the automated procedure by
uncommenting one of a number of lines of code near the start of the
Makefile.PL. (The comments in the Makefile.PL are a clear statement
of what's required for this.)

Note that forcing inclusion of Math::Float128 support will not work
unless the conditions mentioned earlier in this section are met.

==========================================================
Conversion between Math::LongDouble and Math::MPFR objects
==========================================================

There are 2 functions provided for conversion between Math::LongDouble
and Math::MPFR objects:

 Rmpfr_set_LD (assign the value of a Math::LongDouble object to a
               Math::MPFR object)
 Rmpfr_get_LD (assign the value of a Math::MPFR object to a
               Math::Long Double object)

If your perl's nvtype is long double, just use Rmpfr_set_ld and
Rmpfr_get_ld instead.
Math::LongDouble provides 'long double' support for perls whose
nvtype is other than 'long double'.

=======================================================
Conversion between __float128 NV and Math::MPFR objects
=======================================================

To determine your nvtype, run 'perl -V:nvtype'.
As of perl-5.21.4 it is possible to build perl with an nvtype of
__float128. This is achieved by specifying -Dusequadmath as a
Configure arg .... but, it will not work for all architectures
and compilers.

If $Config{nvtype} specifies '__float128' && if your mpfr library
(need 4.0.0 or later) was built with --enable-float128 then you
can pass your __float128 NV values to and from Math::MPFR using
the Rmpfr_set_float128() and Rmpfr_get_float128() functions.
And the overloaded operations will also accept the __float128 NV
arguments as one would want.

This should all be detected and enabled automatically whenever these
conditions are met.
NOTE: Even if the mpfr library was not built with __float128 support
      and the conditions are therefore not met, you can still pass
      and receive __float128 values to/from Math::MPFR by instead
      using the functions Rmpfr_get_NV and Rmpfr_set_NV - but that
      happens only if your nvtype is __float128.

If you wish  you can avoid __float128 support by providing F128=0 as
an argument to the Makefile.PL - ie run 'perl Makefile.PL F128=0';
You can ensure __float128 support by providing the argument F128=1.

Note that forcing inclusion of __float128 support will not work
unless the conditions mentioned earlier in this section are met.

=====
Debug
=====

If the Makefile.PL is given an argument that matches /NVTOA_DEBUG/i
then intermediate values in nvtoa() will be printed to STDERR.
In general, this will produce unwelcome clutter, but the option to
build Math::MPFR with -DNVTOA_DEBUG is there, if it's ever useful.

If the Makefile.PL is given an argument that matches /DTOA_ASSERT/i
then some assertion checks are run at various points in doubletoa().
If the assertion fails, then the program croaks with the relevant
diagnostic  message.

When doubletoa() fails to determine the value of $nv, and falls
back to returning sprintf("%.16e", $nv), then the default
behaviour is to increase $Math::MPFR::doubletoa_fallback by 1.
If you wish to ignore such events, simply provide the Makefie.PL
with the argument FB=0 .
See the doubletoa() documentation in MPFR.pod.

===============================
MS WINDOWS (Visual Studio 2019)
===============================

I don't know how to build the gmp and mpfr libraries using Visual Studio
2019, so when building this module with Visual Studio 2019 I build
against gmp and mpfr libraries that were built using MinGW-w64.

Building with Visual Studio 2019 against  *dynamic* gmp/mpfr libraries
that were built using a MinGW-w64 compiler is not recommended, as strange
results can then arise when calling mpfr functions that take a FILE*
argument.

If building with Visual Studio 2019 against static gmp/mpfr libs that were
built using a MinGW-w64 compiler I first make a copy of the gmp and mpfr
libraries (libgmp.a and libmpfr.a) along with copies of the following
MinGW-w64 library files:
libgcc.a
libgcc_s.a
libmingwex.a
libmingw32.a

For each of the 6 copied files, I leave the filename unchanged (though the
"lib" at the begining of the name is optional), and change the file
extension to ".lib".
In making those copies, I've left them in the same directory as the
original, but I assume (untested) that the copies could be moved to any
location of your choice.

Then build this module by cd'ing to the top level Math::MPFR source folder
and running:

perl Makefile.PL CHECK=0 INC="-IC:/path/to/gmp_header" LIBS="-LC:/path/to/libgcc -lgcc -LC:/path/to/libgcc_s -lgcc_s -LC:/path/to/standard_libs -lmingwex -lmingw32 -LC:/path/to/libgmp -lmpfr -lgmp"
nmake test
nmake install

NOTES
 The given example "perl Makefile.PL ..." command assumes:
  1) that both mpfr.h and gmp.h are in C:/path/to/gmp_header;
  2) that libmingwex and libmingw32 libraries are in the same location;
  3) that libmpfr.lib and libgmp.lib are in C:/path/to/libgmp.
 Modify as necessary.