The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
CHANGES 012
MANIFEST 01
META.json 11
META.yml 11
MPFR.pm 3893
MPFR.xs 371650
Makefile.PL 818
Prec/Prec.pm 44
README 1446
V/V.pm 44
t/D64_LD.t 33
t/_1basic.t 311
t/base_conversion.t 1945
t/decimal64_conv.t 2929
t/float128_conv.t 3030
t/native_float128.t 065
t/new.t 11
t/not_zero.t 15
t/overload.t 37
t/set_NV.t 14
20 files changed (This is a version diff) 5311030
@@ -1,3 +1,15 @@
+3.23
+ - Rename Rmpfr_get_decimal64, Rmpfr_set_decimal64, Rmpfr_get_float128 & Rmpfr_set_float128
+       to Rmpfr_get_DECIMAL64, Rmpfr_set_DECIMAL64, Rmpfr_get_FLOAT128 & Rmpfr_set_FLOAT128
+ - Provide Rmpfr_get_float128 & Rmpfr_set_float128 which pass the __float128 value as an NV
+ - Ensure that when casting an IV/NV to an mpfr_t, the mpfr_t has enough precision to
+   accurately represent the value.
+ - No longer define USE_64_BIT_INT if ivtype is 'long'. (Thus had to tweak some test files.)
+ - Rename USE_64_BIT_INT #define to MATH_MPFR_NEED_LONG_LONG_INT
+ - Define IVSIZE_BITS (in XS file) if MATH_MPFR_NEED_LONG_LONG_INT is defined - for use in
+   initialization of mpfr_t in some of the overload functions.
+ - Add FLOAT128_DIG
+
 3.22
  - Add some metadata to Makefile.PL.
  - Fix the LNGAMMA_BUG workaround in mpfr.c, and change test 69 in t/test1.t to
@@ -31,6 +31,7 @@ t/lngamma_bug.t
 t/LongDouble.t
 t/MPFR_RND.t
 t/nan_cmp.t
+t/native_float128.t
 t/neg_zero_bug.t
 t/not_zero.t
 t/new.t
@@ -27,5 +27,5 @@
          "web" : "https://github.com/sisyphus/math-mpfr"
       }
    },
-   "version" : "3.22"
+   "version" : "3.23"
 }
@@ -16,4 +16,4 @@ no_index:
     - inc
 resources:
   repository: https://github.com/sisyphus/math-mpfr.git
-version: 3.22
+version: 3.23
@@ -28,7 +28,7 @@
     use subs qw(MPFR_VERSION MPFR_VERSION_MAJOR MPFR_VERSION_MINOR
                 MPFR_VERSION_PATCHLEVEL MPFR_VERSION_STRING
                 RMPFR_PREC_MIN RMPFR_PREC_MAX
-                MPFR_DBL_DIG MPFR_LDBL_DIG);
+                MPFR_DBL_DIG MPFR_LDBL_DIG MPFR_FLT128_DIG);
 
     use overload
     '++'   => \&overload_inc,
@@ -130,7 +130,8 @@ Rmpfr_set_nan Rmpfr_set_nanflag Rmpfr_set_overflow Rmpfr_set_prec
 Rmpfr_set_prec_raw Rmpfr_set_q Rmpfr_set_si Rmpfr_set_si_2exp Rmpfr_set_sj
 Rmpfr_set_sj_2exp Rmpfr_set_str Rmpfr_set_str_binary Rmpfr_set_ui Rmpfr_set_ui_2exp
 Rmpfr_set_uj Rmpfr_set_uj_2exp
-Rmpfr_set_decimal64 Rmpfr_get_decimal64 Rmpfr_set_float128 Rmpfr_get_float128
+Rmpfr_set_DECIMAL64 Rmpfr_get_DECIMAL64 Rmpfr_set_float128 Rmpfr_get_float128
+Rmpfr_set_FLOAT128 Rmpfr_get_FLOAT128
 Rmpfr_set_underflow Rmpfr_set_z Rmpfr_sgn Rmpfr_si_div Rmpfr_si_sub Rmpfr_sin
 Rmpfr_sin_cos Rmpfr_sinh_cosh
 Rmpfr_sinh Rmpfr_sqr Rmpfr_sqrt Rmpfr_sqrt_ui Rmpfr_strtofr Rmpfr_sub
@@ -150,11 +151,11 @@ Rmpfr_ai Rmpfr_set_flt Rmpfr_get_flt Rmpfr_urandom Rmpfr_set_z_2exp
 Rmpfr_set_divby0 Rmpfr_clear_divby0 Rmpfr_divby0_p
 Rmpfr_buildopt_tune_case Rmpfr_frexp Rmpfr_grandom Rmpfr_z_sub Rmpfr_buildopt_gmpinternals_p
 prec_cast
-MPFR_DBL_DIG MPFR_LDBL_DIG
+MPFR_DBL_DIG MPFR_LDBL_DIG MPFR_FLT128_DIG
 mpfr_max_orig_len mpfr_min_inter_prec mpfr_min_inter_base mpfr_max_orig_base
 );
 
-    our $VERSION = '3.22';
+    our $VERSION = '3.23';
     #$VERSION = eval $VERSION;
 
     DynaLoader::bootstrap Math::MPFR $VERSION;
@@ -223,7 +224,8 @@ Rmpfr_set_nan Rmpfr_set_nanflag Rmpfr_set_overflow Rmpfr_set_prec
 Rmpfr_set_prec_raw Rmpfr_set_q Rmpfr_set_si Rmpfr_set_si_2exp Rmpfr_set_sj
 Rmpfr_set_sj_2exp Rmpfr_set_str Rmpfr_set_str_binary Rmpfr_set_ui Rmpfr_set_ui_2exp
 Rmpfr_set_uj Rmpfr_set_uj_2exp
-Rmpfr_set_decimal64 Rmpfr_get_decimal64 Rmpfr_set_float128 Rmpfr_get_float128
+Rmpfr_set_DECIMAL64 Rmpfr_get_DECIMAL64 Rmpfr_set_float128 Rmpfr_get_float128
+Rmpfr_set_FLOAT128 Rmpfr_get_FLOAT128
 Rmpfr_set_underflow Rmpfr_set_z Rmpfr_sgn Rmpfr_si_div Rmpfr_si_sub Rmpfr_sin
 Rmpfr_sin_cos Rmpfr_sinh_cosh
 Rmpfr_sinh Rmpfr_sqr Rmpfr_sqrt Rmpfr_sqrt_ui Rmpfr_strtofr Rmpfr_sub
@@ -243,7 +245,7 @@ Rmpfr_ai Rmpfr_set_flt Rmpfr_get_flt Rmpfr_urandom Rmpfr_set_z_2exp
 Rmpfr_set_divby0 Rmpfr_clear_divby0 Rmpfr_divby0_p
 Rmpfr_buildopt_tune_case Rmpfr_frexp Rmpfr_grandom Rmpfr_z_sub Rmpfr_buildopt_gmpinternals_p
 prec_cast
-MPFR_DBL_DIG MPFR_LDBL_DIG
+MPFR_DBL_DIG MPFR_LDBL_DIG MPFR_FLT128_DIG
 mpfr_max_orig_len mpfr_min_inter_prec mpfr_min_inter_base mpfr_max_orig_base
 )]);
 
@@ -517,6 +519,7 @@ sub MPFR_VERSION_PATCHLEVEL {return _MPFR_VERSION_PATCHLEVEL()}
 sub MPFR_VERSION_STRING {return _MPFR_VERSION_STRING()}
 sub MPFR_DBL_DIG {return _DBL_DIG()}
 sub MPFR_LDBL_DIG {return _LDBL_DIG()}
+sub MPFR_FLT128_DIG {return _FLT128_DIG()}
 
 sub mpfr_min_inter_prec {
     die "Wrong number of args to minimum_intermediate_prec()" if @_ != 3;
@@ -747,6 +750,45 @@ Math::MPFR - perl interface to the MPFR (floating point) library.
    segfaults when I try to do that, so I've stopped
    recommending it - and don't support the practice.
 
+=head1 PASSING __float128 VALUES
+
+   There are 3 ways to pass __float128 values to/from
+   Math::MPFR:
+
+    1) Install Math::Float128 and build Math::MPFR by providing the
+    "F128=1" arg to the Makefile.pl:
+
+      perl Makefile.PL F128=1
+
+    Then you can pass the values of the Math::Float128 objects to
+    and from Math::MPFR using:
+
+      Rmpfr_set_FLOAT128() and Rmpfr_get_FLOAT128()
+
+    2) Build perl (5.21.4 or later) with -Dusequadmath; build the
+    mpfr-3.2.0 (or later) library with the configure option
+    --enable-float128, and then build Math::MPFR by providing the
+    "F128=1" arg to the Makefile.pl:
+
+      perl Makefile.PL F128=1
+
+    Then you can pass your perl's __float128 NV values directly
+    to/from Math::MPFR using:
+
+      Rmpfr_set_float128() or Rmpfr_set_NV() and
+      Rmpfr_get_float128() or Rmpfr_get_NV()
+
+    This will also mean that overloaded operations that receive an
+    NV will evaluate that (__float128) NV to it's full precision.
+    And assigning the NV as Math::MPFR->new($nv) will also work as
+    intended.
+
+    3) Convert the __float128 values to a string and pass them to
+    and from Math::MPFR using:
+
+      Rmpfr_set_str() and Rmpfr_get_str()
+
+
 =head1 FUNCTIONS
 
    These next 3 functions are demonstrated above:
@@ -1005,11 +1047,12 @@ Math::MPFR - perl interface to the MPFR (floating point) library.
    $si = Rmpfr_set_q($rop, $q, $rnd); # $q is a mpq object.
    $si = Rmpfr_set_f($rop, $f, $rnd); # $f is a mpf object.
    $si = Rmpfr_set_flt($rop, $float, $rnd); # mpfr-3.0.0 and later only
-   $si = Rmpfr_set_decimal64($rop, $d64, $rnd) # mpfr-3.1.1 and later
-                                               # only. $d64 is a
+   $si = Rmpfr_set_float128($rop, $f128, $rnd); # mpfr-3.2.0 and later
+   $si = Rmpfr_set_DECIMAL64($rop, $D64, $rnd) # mpfr-3.1.1 and later
+                                               # only. $D64 is a
                                                # Math::Decimal64 object
-   $si = Rmpfr_set_float128($rop, $f128, $rnd) # mpfr-3.2.0 and later
-                                               # only. $f128 is a
+   $si = Rmpfr_set_FLOAT128($rop, $F128, $rnd) # mpfr-3.2.0 and later
+                                               # only. $F128 is a
                                                # Math::Float128 object
     Set the value of $rop from 2nd arg, rounded to the precision of
     $rop towards the given direction $rnd.  Please note that even a
@@ -1026,8 +1069,9 @@ Math::MPFR - perl interface to the MPFR (floating point) library.
     Rmpfr_set_NV(), but if your perl's nvtype is 'double' and you want
     to set a value whose precision is that of 'long double', then
     install Math::LongDouble and use Rmpfr_set_LD().
-    Rmpfr_set_NV simply calls either mpfr_set_ld or mpfr_set_ld,
-    as appropriate for your Math::MPFR and perl configuration.
+    Rmpfr_set_NV simply calls either mpfr_set_ld, mpfr_set_ld, or
+    mpfr_set_float128 as appropriate for your Math::MPFR and perl
+    configuration.
 
    $si = Rmpfr_set_ui_2exp($rop, $ui, $exp, $rnd);
    $si = Rmpfr_set_si_2exp($rop, $si, $exp, $rnd);
@@ -1265,18 +1309,20 @@ Math::MPFR - perl interface to the MPFR (floating point) library.
 
    $double = Rmpfr_get_d($op, $rnd);
    $ld     = Rmpfr_get_ld($op, $rnd);
+   $f128   = Rmpfr_get_float128($op, $rnd); # nvtype must be __float128
+                                            # mpfr-3.2.0 or later
    $nv     = Rmpfr_get_NV($op, $rnd);
    $float  = Rmpfr_get_flt($op, $rnd);   # mpfr-3.0.0 and later.
    Rmpfr_get_LD($LD, $op, $rnd); # $LD is a Math::LongDouble object.
-   Rmpfr_get_decimal64($d64, $op, $rnd); # mpfr-3.1.1 and later.
+   Rmpfr_get_DECIMAL64($d64, $op, $rnd); # mpfr-3.1.1 and later.
                                          # $d64 is a Math::Decimal64
                                          # object.
-   Rmpfr_get_float128($f128, $op, $rnd); # mpfr-3.2.0 and later.
-                                         # $f128 is a Math::Float128
+   Rmpfr_get_FLOAT128($F128, $op, $rnd); # mpfr-3.2.0 and later.
+                                         # $F128 is a Math::Float128
                                          # object.
     Convert $op to a 'double' a 'long double' an 'NV', a float, a
-    Math::LongDouble object, a Math::Decimal64 object, or a
-    Math::Float128 object using the rounding mode $rnd.
+    __float128, a Math::LongDouble object, a Math::Decimal64 object, or
+    a Math::Float128 object using the rounding mode $rnd.
 
     NOTE: If your perl's nvtype is 'long double' use Rmpfr_get_ld(), but
     if your perl's nvtype is 'double' and you want to get a value whose
@@ -2218,12 +2264,13 @@ Math::MPFR - perl interface to the MPFR (floating point) library.
      $M ** $G;
 
     In each of the above, a Math::MPFR object containing the result
-    of the operation is returned. It is also now permissible to do:
+    of the operation is returned.It is also now permissible to do:
 
      $M += $G;
      $M -= $G;
      $M *= $G;
      $M /= $G;
+     $M **= $G;
 
     If you have version 0.35 (or later) of Math::GMPz, Math::GMPq
     and Math::GMPf, it is also permissible to do:
@@ -2236,9 +2283,18 @@ Math::MPFR - perl interface to the MPFR (floating point) library.
 
     Again, each of those operations returns a Math::MPFR object
     containing the result of the operation.
-    Each operation is conducted using current default rounding mode
-    and, if there's a need for the operation to create a Math::MPFR
-    object, the created object will be given current default precision.
+    Each operation is conducted using current default rounding mode.
+
+    NOTE: If $G is a Math::GMPq object or a Math::GMPz object, then
+    the value of $G/$M is calculated by doing 1/($M/$G). This
+    involves *2* roundings of the value that is returned - once when
+    $M/$G is calculated, and again when the inverse is calculated.
+
+    NOTE: In overloading a ** (power) operation that involves a
+    Math::GMPq object, it is necessary to convert the Math::GMPq
+    object to an mpfr_t (the type of value encapsulated in the
+    Math::MPFR object). This conversion is done using current default
+    precision and current default rounding mode.
 
     The following is still NOT ALLOWED, and will cause a fatal error:
 
@@ -2255,23 +2311,18 @@ Math::MPFR - perl interface to the MPFR (floating point) library.
     using the first value it finds, or croaking if it gets
     to step 6:
 
-    1. If the variable is an unsigned long then that value is used.
-       The variable is considered to be an unsigned long if
+    1. If the variable is a UV (unsigned integer value) then that
+       value is used. The variable is considered to be a UV if
        (perl 5.8) the UOK flag is set or if (perl 5.6) SvIsUV()
-       returns true.(In the case of perls built with
-       -Duse64bitint, the variable is treated as an unsigned long
-       long int if the UOK flag is set.)
+       returns true.
 
-    2. If the variable is a signed long int, then that value is used.
-       The variable is considered to be a signed long int if the
-       IOK flag is set. (In the case of perls built with
-       -Duse64bitint, the variable is treated as a signed long long
-       int if the IOK flag is set.)
+    2. If the variable is an IV (signed integer value) then that
+       value is used. The variable is considered to be an IV if the
+       IOK flag is set.
 
-    3. If the variable is a double, then that value is used. The
-       variable is considered to be a double if the NOK flag is set.
-       (In the case of perls built with -Duselongdouble, the variable
-       is treated as a long double if the NOK flag is set.)
+    3. If the variable is an NV (floating point value) then that
+       value is used. The variable is considered to be an NV if the
+       NOK flag is set.
 
     4. If the variable is a string (ie the POK flag is set) then the
        value of that string is used. If the POK flag is set, but the
@@ -2382,12 +2433,16 @@ Math::MPFR - perl interface to the MPFR (floating point) library.
 
    BASE CONVERSIONS
 
-   $DBL_DIG  = MPFR_DBL_DIG;  # Will be 0 if float.h doesn't define
+   $DBL_DIG  = MPFR_DBL_DIG;  # Will be undef if float.h doesn't define
                               # DBL_DIG.
 
-   $LDBL_DIG = MPFR_LDBL_DIG; # Will be 0 if float.h doesn't define
+   $LDBL_DIG = MPFR_LDBL_DIG; # Will be undef if float.h doesn't define
                               # LDBL_DIG.
 
+   $FLT128_DIG = MPFR_FLT128_DIG; # Will be undef if quadmath.h has not
+                                  # been loaded, or quadmath.h does not
+                                  # define FLT128_DIG
+.
    $min_prec = mpfr_min_inter_prec($orig_base, $orig_length, $to_base);
    $max_len  = mpfr_max_orig_len($orig_base, $to_base, $to_prec);
    $min_base = mpfr_min_inter_base($orig_base, $orig_length, $to_prec);
@@ -2479,7 +2534,7 @@ Math::MPFR - perl interface to the MPFR (floating point) library.
 
     This program is free software; you may redistribute it and/or
     modify it under the same terms as Perl itself.
-    Copyright 2006-2013 Sisyphus
+    Copyright 2006-2014 Sisyphus
 
 =head1 AUTHOR
 
@@ -14,7 +14,7 @@
 
 #include <stdio.h>
 
-#if defined USE_64_BIT_INT
+#if defined MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
 #include <inttypes.h>
 #endif
@@ -27,6 +27,9 @@
 
 #ifdef MPFR_WANT_FLOAT128
 #include <quadmath.h>
+#if defined(NV_IS_FLOAT128) && defined(MPFR_VERSION) && MPFR_VERSION >= MPFR_VERSION_NUM(3,2,0)
+#define CAN_PASS_FLOAT128
+#endif
 #ifdef __MINGW64__
 typedef __float128 float128 __attribute__ ((aligned(8)));
 #else
@@ -86,7 +89,7 @@ int _has_inttypes(void) {
 #ifdef _MSC_VER
 return 0;
 #else
-#if defined USE_64_BIT_INT
+#if defined MATH_MPFR_NEED_LONG_LONG_INT
 return 1;
 #else
 return 0;
@@ -300,7 +303,7 @@ void Rmpfr_init_set_d(pTHX_ SV * q, SV * round) {
      if(mpfr_t_obj == NULL) croak("Failed to allocate memory in Rmpfr_init_set_d function");
      obj_ref = newSV(0);
      obj = newSVrv(obj_ref, "Math::MPFR");
-     ret = mpfr_init_set_d(*mpfr_t_obj, SvNV(q), (mp_rnd_t)SvUV(round));
+     ret = mpfr_init_set_d(*mpfr_t_obj, (double)SvNV(q), (mp_rnd_t)SvUV(round));
 
      sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
      SvREADONLY_on(obj);
@@ -328,7 +331,7 @@ void Rmpfr_init_set_ld(pTHX_ SV * q, SV * round) {
      if(mpfr_t_obj == NULL) croak("Failed to allocate memory in Rmpfr_init_set_d function");
      obj_ref = newSV(0);
      obj = newSVrv(obj_ref, "Math::MPFR");
-     ret = mpfr_init_set_ld(*mpfr_t_obj, SvNV(q), (mp_rnd_t)SvUV(round));
+     ret = mpfr_init_set_ld(*mpfr_t_obj, (long double)SvNV(q), (mp_rnd_t)SvUV(round));
      sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
      SvREADONLY_on(obj);
      ST(0) = sv_2mortal(obj_ref);
@@ -544,7 +547,7 @@ void Rmpfr_init_set_d_nobless(pTHX_ SV * q, SV * round) {
      if(mpfr_t_obj == NULL) croak("Failed to allocate memory in Rmpfr_init_set_d_nobless function");
      obj_ref = newSV(0);
      obj = newSVrv(obj_ref, NULL);
-     ret = mpfr_init_set_d(*mpfr_t_obj, SvNV(q), (mp_rnd_t)SvUV(round));
+     ret = mpfr_init_set_d(*mpfr_t_obj, (double)SvNV(q), (mp_rnd_t)SvUV(round));
 
      sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
      SvREADONLY_on(obj);
@@ -572,7 +575,7 @@ void Rmpfr_init_set_ld_nobless(pTHX_ SV * q, SV * round) {
      if(mpfr_t_obj == NULL) croak("Failed to allocate memory in Rmpfr_init_set_d_nobless function");
      obj_ref = newSV(0);
      obj = newSVrv(obj_ref, NULL);
-     ret = mpfr_init_set_ld(*mpfr_t_obj, SvNV(q), (mp_rnd_t)SvUV(round));
+     ret = mpfr_init_set_ld(*mpfr_t_obj, (long double)SvNV(q), (mp_rnd_t)SvUV(round));
      sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
      SvREADONLY_on(obj);
      ST(0) = sv_2mortal(obj_ref);
@@ -772,7 +775,7 @@ SV * Rmpfr_set_uj(pTHX_ mpfr_t * p, SV * q, SV * round) {
 #if MPFR_VERSION_MAJOR < 3
     if((mp_rnd_t)SvUV(round) > 3) croak("Illegal rounding value supplied for this version (%s) of the mpfr library", MPFR_VERSION_STRING);
 #endif
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      return newSViv(mpfr_set_uj(*p, SvUV(q), (mp_rnd_t)SvUV(round)));
 #else
@@ -787,7 +790,7 @@ SV * Rmpfr_set_sj(pTHX_ mpfr_t * p, SV * q, SV * round) {
 #if MPFR_VERSION_MAJOR < 3
     if((mp_rnd_t)SvUV(round) > 3) croak("Illegal rounding value supplied for this version (%s) of the mpfr library", MPFR_VERSION_STRING);
 #endif
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      return newSViv(mpfr_set_sj(*p, SvIV(q), (mp_rnd_t)SvUV(round)));
 #else
@@ -802,10 +805,12 @@ SV * Rmpfr_set_NV(pTHX_ mpfr_t * p, SV * q, SV * round) {
 #if MPFR_VERSION_MAJOR < 3
     if((mp_rnd_t)SvUV(round) > 3) croak("Illegal rounding value supplied for this version (%s) of the mpfr library", MPFR_VERSION_STRING);
 #endif
-#if defined(USE_LONG_DOUBLE) && !defined(_MSC_VER)
-     return newSViv(mpfr_set_ld(*p, SvNV(q), (mp_rnd_t)SvUV(round)));
+#if defined(USE_LONG_DOUBLE) && !defined(_MSC_VER) && !defined(CAN_PASS_FLOAT128)
+     return newSViv(mpfr_set_ld(*p, (long double)SvNV(q), (mp_rnd_t)SvUV(round)));
+#elif defined(CAN_PASS_FLOAT128)
+     return newSViv(mpfr_set_float128(*p, (float128)SvNV(q), (mp_rnd_t)SvUV(round)));
 #else
-     return newSViv(mpfr_set_d (*p, SvNV(q), (mp_rnd_t)SvUV(round)));
+     return newSViv(mpfr_set_d (*p, (double)SvNV(q), (mp_rnd_t)SvUV(round)));
 #endif
 }
 
@@ -815,7 +820,7 @@ SV * Rmpfr_set_ld(pTHX_ mpfr_t * p, SV * q, SV * round) {
 #endif
 #ifdef USE_LONG_DOUBLE
 #ifndef _MSC_VER
-     return newSViv(mpfr_set_ld(*p, SvNV(q), (mp_rnd_t)SvUV(round)));
+     return newSViv(mpfr_set_ld(*p, (long double)SvNV(q), (mp_rnd_t)SvUV(round)));
 #else
      croak("Rmpfr_set_ld not implemented on this build of perl - use Rmpfr_set_d instead");
 #endif
@@ -828,7 +833,7 @@ SV * Rmpfr_set_d(pTHX_ mpfr_t * p, SV * q, SV * round) {
 #if MPFR_VERSION_MAJOR < 3
     if((mp_rnd_t)SvUV(round) > 3) croak("Illegal rounding value supplied for this version (%s) of the mpfr library", MPFR_VERSION_STRING);
 #endif
-     return newSViv(mpfr_set_d(*p, SvNV(q), (mp_rnd_t)SvUV(round)));
+     return newSViv(mpfr_set_d(*p, (double)SvNV(q), (mp_rnd_t)SvUV(round)));
 }
 
 SV * Rmpfr_set_z(pTHX_ mpfr_t * p, mpz_t * q, SV * round) {
@@ -1878,10 +1883,8 @@ void Rmpfr_remquo(pTHX_ mpfr_t * a, mpfr_t * b, mpfr_t * c, SV * round) {
     if((mp_rnd_t)SvUV(round) > 3) croak("Illegal rounding value supplied for this version (%s) of the mpfr library", MPFR_VERSION_STRING);
 #endif
      ret = mpfr_remquo(*a, &q, *b, *c, (mp_rnd_t)SvUV(round));
-     /* sp  = mark; *//* not needed */
      ST(0) = sv_2mortal(newSViv(q));
      ST(1) = sv_2mortal(newSViv(ret));
-     /* PUTBACK; *//* not needed */
      XSRETURN(2);
 }
 
@@ -1977,7 +1980,7 @@ SV * Rmpfr_set_uj_2exp(pTHX_ mpfr_t * a, SV * b, SV * c, SV * round) {
 #if MPFR_VERSION_MAJOR < 3
     if((mp_rnd_t)SvUV(round) > 3) croak("Illegal rounding value supplied for this version (%s) of the mpfr library", MPFR_VERSION_STRING);
 #endif
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      return newSViv(mpfr_set_uj_2exp(*a, SvUV(b), SvIV(c), (mp_rnd_t)SvUV(round)));
 #else
@@ -1992,7 +1995,7 @@ SV * Rmpfr_set_sj_2exp(pTHX_ mpfr_t * a, SV * b, SV * c, SV * round) {
 #if MPFR_VERSION_MAJOR < 3
     if((mp_rnd_t)SvUV(round) > 3) croak("Illegal rounding value supplied for this version (%s) of the mpfr library", MPFR_VERSION_STRING);
 #endif
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      return newSViv(mpfr_set_sj_2exp(*a, SvIV(b), SvIV(c), (mp_rnd_t)SvUV(round)));
 #else
@@ -2155,7 +2158,7 @@ SV * Rmpfr_get_uj(pTHX_ mpfr_t * a, SV * round) {
 #if MPFR_VERSION_MAJOR < 3
     if((mp_rnd_t)SvUV(round) > 3) croak("Illegal rounding value supplied for this version (%s) of the mpfr library", MPFR_VERSION_STRING);
 #endif
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
      return newSVuv(mpfr_get_uj(*a, (mp_rnd_t)SvUV(round)));
 #else
      croak ("Rmpfr_get_uj not implemented on this build of perl");
@@ -2166,7 +2169,7 @@ SV * Rmpfr_get_sj(pTHX_ mpfr_t * a, SV * round) {
 #if MPFR_VERSION_MAJOR < 3
     if((mp_rnd_t)SvUV(round) > 3) croak("Illegal rounding value supplied for this version (%s) of the mpfr library", MPFR_VERSION_STRING);
 #endif
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
      return newSViv(mpfr_get_sj(*a, (mp_rnd_t)SvUV(round)));
 #else
      croak ("Rmpfr_get_sj not implemented on this build of perl");
@@ -2177,8 +2180,8 @@ SV * Rmpfr_get_IV(pTHX_ mpfr_t * x, SV * round) {
 #if MPFR_VERSION_MAJOR < 3
     if((mp_rnd_t)SvUV(round) > 3) croak("Illegal rounding value supplied for this version (%s) of the mpfr library", MPFR_VERSION_STRING);
 #endif
-     if(sizeof(IV) == sizeof(int)) return newSViv(mpfr_get_si(*x, (mp_rnd_t)SvUV(round)));
-#if defined USE_64_BIT_INT
+     if(sizeof(IV) == sizeof(long)) return newSViv(mpfr_get_si(*x, (mp_rnd_t)SvUV(round)));
+#if defined MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(sizeof(IV) == sizeof(intmax_t)) return newSViv(mpfr_get_sj(*x, (mp_rnd_t)SvUV(round)));
 #else
@@ -2193,7 +2196,7 @@ SV * Rmpfr_get_UV(pTHX_ mpfr_t * x, SV * round) {
     if((mp_rnd_t)SvUV(round) > 3) croak("Illegal rounding value supplied for this version (%s) of the mpfr library", MPFR_VERSION_STRING);
 #endif
      if(sizeof(UV) == sizeof(unsigned long)) return newSVuv(mpfr_get_ui(*x, (mp_rnd_t)SvUV(round)));
-#if defined USE_64_BIT_INT
+#if defined MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(sizeof(UV) == sizeof(uintmax_t)) return newSVuv(mpfr_get_uj(*x, (mp_rnd_t)SvUV(round)));
 #else
@@ -2207,13 +2210,14 @@ SV * Rmpfr_get_NV(pTHX_ mpfr_t * x, SV * round) {
 #if MPFR_VERSION_MAJOR < 3
     if((mp_rnd_t)SvUV(round) > 3) croak("Illegal rounding value supplied for this version (%s) of the mpfr library", MPFR_VERSION_STRING);
 #endif
-     if(sizeof(NV) == sizeof(double)) return newSVnv(mpfr_get_d(*x, (mp_rnd_t)SvUV(round)));
-#if defined USE_LONG_DOUBLE
-#ifndef _MSC_VER
-     if(sizeof(NV) == sizeof(long double)) return newSVnv(mpfr_get_ld(*x, (mp_rnd_t)SvUV(round)));
-#endif
+#if defined(CAN_PASS_FLOAT128)
+  return newSVnv(mpfr_get_float128(*x, (mp_rnd_t)SvUV(round)));
+#elif defined(USE_LONG_DOUBLE)
+  return newSVnv(mpfr_get_ld(*x, (mp_rnd_t)SvUV(round)));
+#else
+  return newSVnv(mpfr_get_d(*x, (mp_rnd_t)SvUV(round)));
 #endif
-     croak("Rmpfr_get_NV not implemented on this build of perl");
+
 }
 
 SV * Rmpfr_fits_ulong_p(pTHX_ mpfr_t * a, SV * round) {
@@ -2338,7 +2342,7 @@ SV * Rmpfr_fits_IV_p(pTHX_ mpfr_t * x, SV * round) {
        return newSVuv(0);
      }
 
-#if defined USE_64_BIT_INT || defined USE_LONG_DOUBLE
+#if defined MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(sizeof(IV) == sizeof(intmax_t)) {
        if(mpfr_fits_intmax_p(*x, (mp_rnd_t)SvUV(round))) return newSVuv(1);
@@ -2413,7 +2417,7 @@ SV * Rmpfr_fits_UV_p(pTHX_ mpfr_t * x, SV * round) {
 #endif /* MPFR_VERSION */
      }
 
-#if defined USE_64_BIT_INT || defined USE_LONG_DOUBLE
+#if defined MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(sizeof(UV) == sizeof(uintmax_t)) {
 #if defined(MPFR_VERSION) && MPFR_VERSION > NEG_ZERO_BUG
@@ -2447,7 +2451,7 @@ SV * Rmpfr_fits_UV_p(pTHX_ mpfr_t * x, SV * round) {
 #endif /* MPFR_VERSION */
      }
 #endif /* MSC_VER */
-#endif /* USE_64_BIT_INT */
+#endif /* MATH_MPFR_NEED_LONG_LONG_INT */
 
      mpfr_init2(high, bits + 1);
      mpfr_init2(copy, bits);
@@ -2723,10 +2727,8 @@ SV * Rmpfr_sum(pTHX_ mpfr_t * rop, SV * avref, SV * len, SV * round) {
      return newSVuv(ret);
 }
 
-/* Finish typemapping - typemap 1st arg only */
-
 SV * overload_mul(pTHX_ SV * a, SV * b, SV * third) {
-     mpfr_t * mpfr_t_obj;
+     mpfr_t * mpfr_t_obj, t;
      SV * obj_ref, * obj;
 
      Newx(mpfr_t_obj, 1, mpfr_t);
@@ -2737,17 +2739,21 @@ SV * overload_mul(pTHX_ SV * a, SV * b, SV * third) {
      sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
      SvREADONLY_on(obj);
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_set_uj(*mpfr_t_obj, SvUV(b), __gmpfr_default_rounding_mode);
-       mpfr_mul(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
+       mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
+       mpfr_mul(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
        return obj_ref;
      }
 
      if(SvIOK(b)) {
-       mpfr_set_sj(*mpfr_t_obj, SvIV(b), __gmpfr_default_rounding_mode);
-       mpfr_mul(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
+       mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
+       mpfr_mul(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
        return obj_ref;
      }
 #else
@@ -2765,30 +2771,38 @@ SV * overload_mul(pTHX_ SV * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
-       if(SvIV(b) >= 0) {
-         mpfr_mul_ui(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvUV(b), __gmpfr_default_rounding_mode);
-         return obj_ref;
-       }
-       mpfr_mul_ui(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b) * -1, __gmpfr_default_rounding_mode);
-       mpfr_neg(*mpfr_t_obj, *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_mul_si(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b), __gmpfr_default_rounding_mode);
        return obj_ref;
      }
 #endif
 
      if(SvNOK(b)) {
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       mpfr_set_ld(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#else
-       mpfr_set_d(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
+
+#if defined(CAN_PASS_FLOAT128)
+
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+       mpfr_mul(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
+       return obj_ref;
+     }
+
+#elif defined(USE_LONG_DOUBLE)
+
+       mpfr_init2(t, LDBL_MANT_DIG);
+       mpfr_set_ld(t, (long double)SvNV(b), __gmpfr_default_rounding_mode);
+       mpfr_mul(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
+       return obj_ref;
+     }
+
 #else
-       mpfr_set_d(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
-       mpfr_mul(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_mul_d(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), (double)SvNV(b), __gmpfr_default_rounding_mode);
        return obj_ref;
      }
 
+#endif
+
      if(SvPOK(b)) {
        if(mpfr_set_str(*mpfr_t_obj, SvPV_nolen(b), 0, __gmpfr_default_rounding_mode))
          croak("Invalid string supplied to Math::MPFR::overload_mul");
@@ -2804,18 +2818,24 @@ SV * overload_mul(pTHX_ SV * a, SV * b, SV * third) {
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPz")) {
-         mpfr_set_z(*mpfr_t_obj, *(INT2PTR(mpz_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
-         mpfr_mul(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+
+         mpfr_mul_z(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))),
+                                 *(INT2PTR(mpz_t * , SvIV(SvRV(b)))),
+                                 __gmpfr_default_rounding_mode);
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPq")) {
-         mpfr_set_q(*mpfr_t_obj, *(INT2PTR(mpq_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
-         mpfr_mul(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+
+         mpfr_mul_q(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))),
+                                 *(INT2PTR(mpq_t * , SvIV(SvRV(b)))),
+                                 __gmpfr_default_rounding_mode);
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPf")) {
-         mpfr_set_f(*mpfr_t_obj, *(INT2PTR(mpf_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
-         mpfr_mul(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+         mpfr_init2(t, (mpfr_prec_t)mpf_get_prec(*(INT2PTR(mpf_t *, SvIV(SvRV(b))))));
+         mpfr_set_f(t, *(INT2PTR(mpf_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
+         mpfr_mul(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+         mpfr_clear(t);
          return obj_ref;
        }
      }
@@ -2824,7 +2844,7 @@ SV * overload_mul(pTHX_ SV * a, SV * b, SV * third) {
 }
 
 SV * overload_add(pTHX_ SV * a, SV * b, SV * third) {
-     mpfr_t * mpfr_t_obj;
+     mpfr_t * mpfr_t_obj, t;
      SV * obj_ref, * obj;
 
      Newx(mpfr_t_obj, 1, mpfr_t);
@@ -2835,17 +2855,21 @@ SV * overload_add(pTHX_ SV * a, SV * b, SV * third) {
      sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
      SvREADONLY_on(obj);
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_set_uj(*mpfr_t_obj, SvUV(b), __gmpfr_default_rounding_mode);
-       mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
+       mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
+       mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
        return obj_ref;
      }
 
      if(SvIOK(b)) {
-       mpfr_set_sj(*mpfr_t_obj, SvIV(b), __gmpfr_default_rounding_mode);
-       mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
+       mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
+       mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
        return obj_ref;
      }
 #else
@@ -2863,29 +2887,37 @@ SV * overload_add(pTHX_ SV * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
-       if(SvIV(b) >= 0) {
-         mpfr_add_ui(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvUV(b), __gmpfr_default_rounding_mode);
-         return obj_ref;
-       }
-       mpfr_sub_ui(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b) * -1, __gmpfr_default_rounding_mode);
+       mpfr_add_si(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b), __gmpfr_default_rounding_mode);
        return obj_ref;
      }
 #endif
 
      if(SvNOK(b)) {
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       mpfr_set_ld(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#else
-       mpfr_set_d(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
+#if defined(CAN_PASS_FLOAT128)
+
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+       mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
+       return obj_ref;
+     }
+
+#elif defined(USE_LONG_DOUBLE)
+
+       mpfr_init2(t, LDBL_MANT_DIG);
+       mpfr_set_ld(t, (long double)SvNV(b), __gmpfr_default_rounding_mode);
+       mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
+       return obj_ref;
+     }
+
 #else
-       mpfr_set_d(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
-       mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_add_d(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), (double)SvNV(b), __gmpfr_default_rounding_mode);
        return obj_ref;
      }
 
+#endif
+
      if(SvPOK(b)) {
        if(mpfr_set_str(*mpfr_t_obj, SvPV_nolen(b), 0, __gmpfr_default_rounding_mode))
          croak("Invalid string supplied to Math::MPFR::overload_add");
@@ -2897,22 +2929,28 @@ SV * overload_add(pTHX_ SV * a, SV * b, SV * third) {
        const char* h = HvNAME(SvSTASH(SvRV(b)));
 
        if(strEQ(h, "Math::MPFR")) {
-         mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
+         mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))),
+                               *(INT2PTR(mpfr_t *, SvIV(SvRV(b)))),
+                               __gmpfr_default_rounding_mode);
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPz")) {
-         mpfr_set_z(*mpfr_t_obj, *(INT2PTR(mpz_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
-         mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+         mpfr_add_z(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))),
+                                 *(INT2PTR(mpz_t * , SvIV(SvRV(b)))),
+                                 __gmpfr_default_rounding_mode);
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPq")) {
-         mpfr_set_q(*mpfr_t_obj, *(INT2PTR(mpq_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
-         mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+         mpfr_add_q(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))),
+                                 *(INT2PTR(mpq_t * , SvIV(SvRV(b)))),
+                                 __gmpfr_default_rounding_mode);
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPf")) {
-         mpfr_set_f(*mpfr_t_obj, *(INT2PTR(mpf_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
-         mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+         mpfr_init2(t, (mpfr_prec_t)mpf_get_prec(*(INT2PTR(mpf_t *, SvIV(SvRV(b))))));
+         mpfr_set_f(t, *(INT2PTR(mpf_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
+         mpfr_add(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+         mpfr_clear(t);
          return obj_ref;
        }
      }
@@ -2921,7 +2959,7 @@ SV * overload_add(pTHX_ SV * a, SV * b, SV * third) {
 }
 
 SV * overload_sub(pTHX_ SV * a, SV * b, SV * third) {
-     mpfr_t * mpfr_t_obj;
+     mpfr_t * mpfr_t_obj, t;
      SV * obj_ref, * obj;
 
      Newx(mpfr_t_obj, 1, mpfr_t);
@@ -2932,19 +2970,23 @@ SV * overload_sub(pTHX_ SV * a, SV * b, SV * third) {
      sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
      SvREADONLY_on(obj);
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_set_uj(*mpfr_t_obj, SvUV(b), __gmpfr_default_rounding_mode);
-       if(third == &PL_sv_yes) mpfr_sub(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-       else mpfr_sub(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
+       mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
+       if(third == &PL_sv_yes) mpfr_sub(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+       else mpfr_sub(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
        return obj_ref;
      }
 
      if(SvIOK(b)) {
-       mpfr_set_sj(*mpfr_t_obj, SvIV(b), __gmpfr_default_rounding_mode);
-       if(third == &PL_sv_yes) mpfr_sub(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-       else mpfr_sub(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
+       mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
+       if(third == &PL_sv_yes) mpfr_sub(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+       else mpfr_sub(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
        return obj_ref;
      }
 #else
@@ -2964,32 +3006,42 @@ SV * overload_sub(pTHX_ SV * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
-       if(SvIV(b) >= 0) {
-         if(third == &PL_sv_yes) mpfr_ui_sub(*mpfr_t_obj, SvUV(b), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-         else mpfr_sub_ui(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvUV(b), __gmpfr_default_rounding_mode);
-         return obj_ref;
-       }
-       mpfr_add_ui(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b) * -1, __gmpfr_default_rounding_mode);
-       if(third == &PL_sv_yes) mpfr_neg(*mpfr_t_obj, *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       if(third == &PL_sv_yes) mpfr_si_sub(*mpfr_t_obj, SvIV(b), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+       else mpfr_sub_si(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b), __gmpfr_default_rounding_mode);
        return obj_ref;
      }
 #endif
 
      if(SvNOK(b)) {
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       mpfr_set_ld(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#else
-       mpfr_set_d(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
+#if defined(CAN_PASS_FLOAT128)
+
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+       if(third == &PL_sv_yes) mpfr_sub(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+       else mpfr_sub(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
+       return obj_ref;
+     }
+#elif defined(USE_LONG_DOUBLE)
+
+       mpfr_init2(t, LDBL_MANT_DIG);
+       mpfr_set_ld(t, (long double)SvNV(b), __gmpfr_default_rounding_mode);
+       if(third == &PL_sv_yes) mpfr_sub(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+       else mpfr_sub(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
+       return obj_ref;
+     }
+
 #else
-       mpfr_set_d(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
-       if(third == &PL_sv_yes) mpfr_sub(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-       else mpfr_sub(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+
+       if(third == &PL_sv_yes) mpfr_d_sub(*mpfr_t_obj, SvNV(b), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+       else mpfr_sub_d(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvNV(b), __gmpfr_default_rounding_mode);
        return obj_ref;
      }
 
+#endif
+
+
      if(SvPOK(b)) {
        if(mpfr_set_str(*mpfr_t_obj, SvPV_nolen(b), 0, __gmpfr_default_rounding_mode))
          croak("Invalid string supplied to Math::MPFR::overload_sub");
@@ -3006,21 +3058,25 @@ SV * overload_sub(pTHX_ SV * a, SV * b, SV * third) {
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPz")) {
-         mpfr_set_z(*mpfr_t_obj, *(INT2PTR(mpz_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
-         if(third == &PL_sv_yes) mpfr_sub(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-         else mpfr_sub(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+         mpfr_sub_z(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))),
+                                      *(INT2PTR(mpz_t * , SvIV(SvRV(b)))),
+                                      __gmpfr_default_rounding_mode);
+         if(third == &PL_sv_yes) mpfr_neg(*mpfr_t_obj, *mpfr_t_obj, MPFR_RNDN);
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPq")) {
-         mpfr_set_q(*mpfr_t_obj, *(INT2PTR(mpq_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
-         if(third == &PL_sv_yes) mpfr_sub(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-         else mpfr_sub(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+         mpfr_sub_q(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))),
+                                      *(INT2PTR(mpq_t * , SvIV(SvRV(b)))),
+                                      __gmpfr_default_rounding_mode);
+         if(third == &PL_sv_yes) mpfr_neg(*mpfr_t_obj, *mpfr_t_obj, MPFR_RNDN);
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPf")) {
-         mpfr_set_f(*mpfr_t_obj, *(INT2PTR(mpf_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
-         if(third == &PL_sv_yes) mpfr_sub(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-         else mpfr_sub(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+         mpfr_init2(t, (mpfr_prec_t)mpf_get_prec(*(INT2PTR(mpf_t *, SvIV(SvRV(b))))));
+         mpfr_set_f(t, *(INT2PTR(mpf_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
+         if(third == &PL_sv_yes) mpfr_sub(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+         else mpfr_sub(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+         mpfr_clear(t);
          return obj_ref;
        }
      }
@@ -3029,7 +3085,7 @@ SV * overload_sub(pTHX_ SV * a, SV * b, SV * third) {
 }
 
 SV * overload_div(pTHX_ SV * a, SV * b, SV * third) {
-     mpfr_t * mpfr_t_obj;
+     mpfr_t * mpfr_t_obj, t;
      SV * obj_ref, * obj;
 
      Newx(mpfr_t_obj, 1, mpfr_t);
@@ -3040,19 +3096,23 @@ SV * overload_div(pTHX_ SV * a, SV * b, SV * third) {
      sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
      SvREADONLY_on(obj);
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_set_uj(*mpfr_t_obj, SvUV(b), __gmpfr_default_rounding_mode);
-       if(third == &PL_sv_yes) mpfr_div(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-       else mpfr_div(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
+       mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
+       if(third == &PL_sv_yes) mpfr_div(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+       else mpfr_div(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
        return obj_ref;
      }
 
      if(SvIOK(b)) {
-       mpfr_set_sj(*mpfr_t_obj, SvIV(b), __gmpfr_default_rounding_mode);
-       if(third == &PL_sv_yes) mpfr_div(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-       else mpfr_div(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
+       mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
+       if(third == &PL_sv_yes) mpfr_div(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+       else mpfr_div(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
        return obj_ref;
      }
 #else
@@ -3072,33 +3132,42 @@ SV * overload_div(pTHX_ SV * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
-       if(SvIV(b) >= 0) {
-         if(third == &PL_sv_yes) mpfr_ui_div(*mpfr_t_obj, SvUV(b), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-         else mpfr_div_ui(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvUV(b), __gmpfr_default_rounding_mode);
-         return obj_ref;
-       }
-       if(third == &PL_sv_yes) mpfr_ui_div(*mpfr_t_obj, SvIV(b) * -1, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-       else mpfr_div_ui(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b) * -1, __gmpfr_default_rounding_mode);
-       mpfr_neg(*mpfr_t_obj, *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       if(third == &PL_sv_yes) mpfr_si_div(*mpfr_t_obj, SvIV(b), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+       else mpfr_div_si(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b), __gmpfr_default_rounding_mode);
        return obj_ref;
      }
 #endif
 
      if(SvNOK(b)) {
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       mpfr_set_ld(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#else
-       mpfr_set_d(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
+#if defined(CAN_PASS_FLOAT128)
+
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+       if(third == &PL_sv_yes) mpfr_div(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+       else mpfr_div(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       return obj_ref;
+       mpfr_clear(t);
+     }
+
+#elif defined(USE_LONG_DOUBLE)
+
+       mpfr_init2(t, LDBL_MANT_DIG);
+       mpfr_set_ld(t, (long double)SvNV(b), __gmpfr_default_rounding_mode);
+       if(third == &PL_sv_yes) mpfr_div(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+       else mpfr_div(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
+       return obj_ref;
+     }
+
 #else
-       mpfr_set_d(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
-       if(third == &PL_sv_yes) mpfr_div(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-       else mpfr_div(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+
+       if(third == &PL_sv_yes) mpfr_d_div(*mpfr_t_obj, SvNV(b), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+       else mpfr_div_d(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvNV(b), __gmpfr_default_rounding_mode);
        return obj_ref;
      }
 
+#endif
+
      if(SvPOK(b)) {
        if(mpfr_set_str(*mpfr_t_obj, SvPV_nolen(b), 0, __gmpfr_default_rounding_mode))
          croak("Invalid string supplied to Math::MPFR::overload_div");
@@ -3115,21 +3184,27 @@ SV * overload_div(pTHX_ SV * a, SV * b, SV * third) {
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPz")) {
-         mpfr_set_z(*mpfr_t_obj, *(INT2PTR(mpz_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
-         if(third == &PL_sv_yes) mpfr_div(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-         else mpfr_div(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+         mpfr_div_z(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))),
+                                      *(INT2PTR(mpz_t * , SvIV(SvRV(b)))),
+                                      __gmpfr_default_rounding_mode);
+         /* *mpfr_t_obj gets rounded a second time if third == &PL_sv_yes */
+         if(third == &PL_sv_yes) mpfr_ui_div(*mpfr_t_obj, 1, *mpfr_t_obj, __gmpfr_default_rounding_mode);
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPq")) {
-         mpfr_set_q(*mpfr_t_obj, *(INT2PTR(mpq_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
-         if(third == &PL_sv_yes) mpfr_div(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-         else mpfr_div(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+         mpfr_div_q(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))),
+                                      *(INT2PTR(mpq_t * , SvIV(SvRV(b)))),
+                                      __gmpfr_default_rounding_mode);
+         /* *mpfr_t_obj gets rounded a second time if third == &PL_sv_yes */
+         if(third == &PL_sv_yes) mpfr_ui_div(*mpfr_t_obj, 1, *mpfr_t_obj, __gmpfr_default_rounding_mode);
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPf")) {
-         mpfr_set_f(*mpfr_t_obj, *(INT2PTR(mpf_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
-         if(third == &PL_sv_yes) mpfr_div(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
-         else mpfr_div(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+         mpfr_init2(t, (mpfr_prec_t)mpf_get_prec(*(INT2PTR(mpf_t *, SvIV(SvRV(b))))));
+         mpfr_set_f(t, *(INT2PTR(mpf_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
+         if(third == &PL_sv_yes) mpfr_div(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
+         else mpfr_div(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
+         mpfr_clear(t);
          return obj_ref;
        }
      }
@@ -3178,10 +3253,10 @@ SV * overload_gt(pTHX_ mpfr_t * a, SV * b, SV * third) {
        return newSVuv(0);
      }
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3191,7 +3266,7 @@ SV * overload_gt(pTHX_ mpfr_t * a, SV * b, SV * third) {
        }
 
      if(SvIOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3233,14 +3308,15 @@ SV * overload_gt(pTHX_ mpfr_t * a, SV * b, SV * third) {
          return newSVuv(0);
        }
 
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       ret = mpfr_cmp_ld(*a, SvNV(b));
-#else
-       ret = mpfr_cmp_d(*a, SvNV(b));
-#endif
+#if defined(CAN_PASS_FLOAT128)
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+       ret = mpfr_cmp(*a, t);
+       mpfr_clear(t);
+#elif defined(USE_LONG_DOUBLE)
+       ret = mpfr_cmp_ld(*a, (long double)SvNV(b));
 #else
-       ret = mpfr_cmp_d(*a, SvNV(b));
+       ret = mpfr_cmp_d(*a, (double)SvNV(b));
 #endif
        if(third == &PL_sv_yes) ret *= -1;
        if(ret > 0) return newSViv(1);
@@ -3277,10 +3353,10 @@ SV * overload_gte(pTHX_ mpfr_t * a, SV * b, SV * third) {
        return newSVuv(0);
      }
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3290,7 +3366,7 @@ SV * overload_gte(pTHX_ mpfr_t * a, SV * b, SV * third) {
        }
 
      if(SvIOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3332,15 +3408,17 @@ SV * overload_gte(pTHX_ mpfr_t * a, SV * b, SV * third) {
          return newSVuv(0);
        }
 
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       ret = mpfr_cmp_ld(*a, SvNV(b));
-#else
-       ret = mpfr_cmp_d(*a, SvNV(b));
-#endif
+#if defined(CAN_PASS_FLOAT128)
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+       ret = mpfr_cmp(*a, t);
+       mpfr_clear(t);
+#elif defined(USE_LONG_DOUBLE)
+       ret = mpfr_cmp_ld(*a, (long double)SvNV(b));
 #else
-       ret = mpfr_cmp_d(*a, SvNV(b));
+       ret = mpfr_cmp_d(*a, (double)SvNV(b));
 #endif
+
        if(third == &PL_sv_yes) ret *= -1;
        if(ret >= 0) return newSViv(1);
        return newSViv(0);
@@ -3376,10 +3454,10 @@ SV * overload_lt(pTHX_ mpfr_t * a, SV * b, SV * third) {
        return newSVuv(0);
      }
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3389,7 +3467,7 @@ SV * overload_lt(pTHX_ mpfr_t * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3431,15 +3509,17 @@ SV * overload_lt(pTHX_ mpfr_t * a, SV * b, SV * third) {
          return newSVuv(0);
        }
 
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       ret = mpfr_cmp_ld(*a, SvNV(b));
-#else
-       ret = mpfr_cmp_d(*a, SvNV(b));
-#endif
+#if defined(CAN_PASS_FLOAT128)
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+       ret = mpfr_cmp(*a, t);
+       mpfr_clear(t);
+#elif defined(USE_LONG_DOUBLE)
+       ret = mpfr_cmp_ld(*a, (long double)SvNV(b));
 #else
-       ret = mpfr_cmp_d(*a, SvNV(b));
+       ret = mpfr_cmp_d(*a, (double)SvNV(b));
 #endif
+
        if(third == &PL_sv_yes) ret *= -1;
        if(ret < 0) return newSViv(1);
        return newSViv(0);
@@ -3475,10 +3555,10 @@ SV * overload_lte(pTHX_ mpfr_t * a, SV * b, SV * third) {
        return newSVuv(0);
      }
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3488,7 +3568,7 @@ SV * overload_lte(pTHX_ mpfr_t * a, SV * b, SV * third) {
        }
 
      if(SvIOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3530,15 +3610,17 @@ SV * overload_lte(pTHX_ mpfr_t * a, SV * b, SV * third) {
          return newSVuv(0);
        }
 
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       ret = mpfr_cmp_ld(*a, SvNV(b));
-#else
-       ret = mpfr_cmp_d(*a, SvNV(b));
-#endif
+#if defined(CAN_PASS_FLOAT128)
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+       ret = mpfr_cmp(*a, t);
+       mpfr_clear(t);
+#elif defined(USE_LONG_DOUBLE)
+       ret = mpfr_cmp_ld(*a, (long double)SvNV(b));
 #else
-       ret = mpfr_cmp_d(*a, SvNV(b));
+       ret = mpfr_cmp_d(*a, (double)SvNV(b));
 #endif
+
        if(third == &PL_sv_yes) ret *= -1;
        if(ret <= 0) return newSViv(1);
        return newSViv(0);
@@ -3573,10 +3655,10 @@ SV * overload_spaceship(pTHX_ mpfr_t * a, SV * b, SV * third) {
        return &PL_sv_undef;
      }
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3587,7 +3669,7 @@ SV * overload_spaceship(pTHX_ mpfr_t * a, SV * b, SV * third) {
        }
 
      if(SvIOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3633,15 +3715,17 @@ SV * overload_spaceship(pTHX_ mpfr_t * a, SV * b, SV * third) {
        return &PL_sv_undef;
      }
 
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       ret = mpfr_cmp_ld(*a, SvNV(b));
-#else
-       ret = mpfr_cmp_d(*a, SvNV(b));
-#endif
+#if defined(CAN_PASS_FLOAT128)
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+       ret = mpfr_cmp(*a, t);
+       mpfr_clear(t);
+#elif defined(USE_LONG_DOUBLE)
+       ret = mpfr_cmp_ld(*a, (long double)SvNV(b));
 #else
-       ret = mpfr_cmp_d(*a, SvNV(b));
+       ret = mpfr_cmp_d(*a, (double)SvNV(b));
 #endif
+
        if(third == &PL_sv_yes) ret *= -1;
        if(ret < 0) return newSViv(-1);
        if(ret > 0) return newSViv(1);
@@ -3679,10 +3763,10 @@ SV * overload_equiv(pTHX_ mpfr_t * a, SV * b, SV * third) {
        return newSVuv(0);
      }
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3691,7 +3775,7 @@ SV * overload_equiv(pTHX_ mpfr_t * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3729,15 +3813,17 @@ SV * overload_equiv(pTHX_ mpfr_t * a, SV * b, SV * third) {
          return newSVuv(0);
        }
 
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       ret = mpfr_cmp_ld(*a, SvNV(b));
-#else
-       ret = mpfr_cmp_d(*a, SvNV(b));
-#endif
+#if defined(CAN_PASS_FLOAT128)
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+       ret = mpfr_cmp(*a, t);
+       mpfr_clear(t);
+#elif defined(USE_LONG_DOUBLE)
+       ret = mpfr_cmp_ld(*a, (long double)SvNV(b));
 #else
-       ret = mpfr_cmp_d(*a, SvNV(b));
+       ret = mpfr_cmp_d(*a, (double)SvNV(b));
 #endif
+
        if(ret == 0) return newSViv(1);
        return newSViv(0);
      }
@@ -3771,10 +3857,10 @@ SV * overload_not_equiv(pTHX_ mpfr_t * a, SV * b, SV * third) {
        return newSVuv(1);
      }
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3783,7 +3869,7 @@ SV * overload_not_equiv(pTHX_ mpfr_t * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
        ret = mpfr_cmp(*a, t);
        mpfr_clear(t);
@@ -3821,15 +3907,17 @@ SV * overload_not_equiv(pTHX_ mpfr_t * a, SV * b, SV * third) {
          return newSVuv(1);
        }
 
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       ret = mpfr_cmp_ld(*a, SvNV(b));
-#else
-       ret = mpfr_cmp_d(*a, SvNV(b));
-#endif
+#if defined(CAN_PASS_FLOAT128)
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+       ret = mpfr_cmp(*a, t);
+       mpfr_clear(t);
+#elif defined(USE_LONG_DOUBLE)
+       ret = mpfr_cmp_ld(*a, (long double)SvNV(b));
 #else
-       ret = mpfr_cmp_d(*a, SvNV(b));
+       ret = mpfr_cmp_d(*a, (double)SvNV(b));
 #endif
+
        if(ret != 0) return newSViv(1);
        return newSViv(0);
      }
@@ -3887,7 +3975,7 @@ SV * overload_sqrt(pTHX_ mpfr_t * p, SV * second, SV * third) {
 }
 
 SV * overload_pow(pTHX_ SV * p, SV * second, SV * third) {
-     mpfr_t * mpfr_t_obj;
+     mpfr_t * mpfr_t_obj, t;
      SV * obj_ref, * obj;
 
      Newx(mpfr_t_obj, 1, mpfr_t);
@@ -3898,19 +3986,23 @@ SV * overload_pow(pTHX_ SV * p, SV * second, SV * third) {
      sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
      SvREADONLY_on(obj);
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(second)) {
-       mpfr_set_uj(*mpfr_t_obj, SvUV(second), __gmpfr_default_rounding_mode);
-       if(third == &PL_sv_yes) mpfr_pow(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), __gmpfr_default_rounding_mode);
-       else mpfr_pow(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
+       mpfr_set_uj(t, SvUV(second), __gmpfr_default_rounding_mode);
+       if(third == &PL_sv_yes) mpfr_pow(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), __gmpfr_default_rounding_mode);
+       else mpfr_pow(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
        return obj_ref;
      }
 
      if(SvIOK(second)) {
-       mpfr_set_sj(*mpfr_t_obj, SvIV(second), __gmpfr_default_rounding_mode);
-       if(third == &PL_sv_yes) mpfr_pow(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), __gmpfr_default_rounding_mode);
-       else mpfr_pow(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
+       mpfr_set_sj(t, SvIV(second), __gmpfr_default_rounding_mode);
+       if(third == &PL_sv_yes) mpfr_pow(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), __gmpfr_default_rounding_mode);
+       else mpfr_pow(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
        return obj_ref;
      }
 #else
@@ -3930,6 +4022,7 @@ SV * overload_pow(pTHX_ SV * p, SV * second, SV * third) {
      }
 
      if(SvIOK(second)) {
+       /* Need to do it this way as there's no mpfr_si_pow function */
        if(SvIV(second) >= 0) {
          if(third == &PL_sv_yes) mpfr_ui_pow(*mpfr_t_obj, SvUV(second), *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), __gmpfr_default_rounding_mode);
          else mpfr_pow_ui(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), SvUV(second), __gmpfr_default_rounding_mode);
@@ -3943,17 +4036,27 @@ SV * overload_pow(pTHX_ SV * p, SV * second, SV * third) {
 #endif
 
      if(SvNOK(second)) {
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       mpfr_set_ld(*mpfr_t_obj, SvNV(second), __gmpfr_default_rounding_mode);
-#else
-       mpfr_set_d(*mpfr_t_obj, SvNV(second), __gmpfr_default_rounding_mode);
-#endif
+
+#if defined(CAN_PASS_FLOAT128)
+
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(second), __gmpfr_default_rounding_mode);
+
+#elif defined(USE_LONG_DOUBLE)
+
+       mpfr_init2(t, LDBL_MANT_DIG);
+       mpfr_set_ld(t, (long double)SvNV(second), __gmpfr_default_rounding_mode);
+
 #else
-       mpfr_set_d(*mpfr_t_obj, SvNV(second), __gmpfr_default_rounding_mode);
+
+       mpfr_init2(t, DBL_MANT_DIG);
+       mpfr_set_d(t, (double)SvNV(second), __gmpfr_default_rounding_mode);
+
 #endif
-       if(third == &PL_sv_yes) mpfr_pow(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), __gmpfr_default_rounding_mode);
-       else mpfr_pow(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+
+       if(third == &PL_sv_yes) mpfr_pow(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), __gmpfr_default_rounding_mode);
+       else mpfr_pow(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), t, __gmpfr_default_rounding_mode);
+       mpfr_clear(t);
        return obj_ref;
      }
 
@@ -3973,9 +4076,15 @@ SV * overload_pow(pTHX_ SV * p, SV * second, SV * third) {
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPz")) {
-         mpfr_set_z(*mpfr_t_obj, *(INT2PTR(mpz_t *, SvIV(SvRV(second)))), __gmpfr_default_rounding_mode);
-         if(third == &PL_sv_yes) mpfr_pow(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), __gmpfr_default_rounding_mode);
-         else mpfr_pow(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+         if(third == &PL_sv_yes) {
+           mpfr_init2(t, (mpfr_prec_t)mpz_sizeinbase(*(INT2PTR(mpz_t *, SvIV(SvRV(second)))), 2));
+           mpfr_set_z(t, *(INT2PTR(mpz_t *, SvIV(SvRV(second)))), __gmpfr_default_rounding_mode);
+           mpfr_pow(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), __gmpfr_default_rounding_mode);
+           mpfr_clear(t);
+         }
+         else mpfr_pow_z(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p     )))),
+                                      *(INT2PTR(mpz_t * , SvIV(SvRV(second)))),
+                                      __gmpfr_default_rounding_mode);
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPq")) {
@@ -3985,9 +4094,11 @@ SV * overload_pow(pTHX_ SV * p, SV * second, SV * third) {
          return obj_ref;
        }
        if(strEQ(h, "Math::GMPf")) {
-         mpfr_set_f(*mpfr_t_obj, *(INT2PTR(mpf_t *, SvIV(SvRV(second)))), __gmpfr_default_rounding_mode);
-         if(third == &PL_sv_yes) mpfr_pow(*mpfr_t_obj, *mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), __gmpfr_default_rounding_mode);
-         else mpfr_pow(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), *mpfr_t_obj, __gmpfr_default_rounding_mode);
+         mpfr_init2(t, (mpfr_prec_t)mpf_get_prec(*(INT2PTR(mpf_t *, SvIV(SvRV(second))))));
+         mpfr_set_f(t, *(INT2PTR(mpf_t *, SvIV(SvRV(second)))), __gmpfr_default_rounding_mode);
+         if(third == &PL_sv_yes) mpfr_pow(*mpfr_t_obj, t, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), __gmpfr_default_rounding_mode);
+         else mpfr_pow(*mpfr_t_obj, *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), t, __gmpfr_default_rounding_mode);
+         mpfr_clear(t);
          return obj_ref;
        }
      }
@@ -4076,7 +4187,7 @@ SV * overload_int(pTHX_ mpfr_t * p, SV * second, SV * third) {
 }
 
 SV * overload_atan2(pTHX_ mpfr_t * a, SV * b, SV * third) {
-     mpfr_t * mpfr_t_obj;
+     mpfr_t * mpfr_t_obj, t;
      SV * obj_ref, * obj;
 
      Newx(mpfr_t_obj, 1, mpfr_t);
@@ -4085,29 +4196,33 @@ SV * overload_atan2(pTHX_ mpfr_t * a, SV * b, SV * third) {
      obj = newSVrv(obj_ref, "Math::MPFR");
      mpfr_init(*mpfr_t_obj);
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_set_uj(*mpfr_t_obj, SvUV(b), __gmpfr_default_rounding_mode);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
+       mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
        if(third == &PL_sv_yes){
-         mpfr_atan2(*mpfr_t_obj, *mpfr_t_obj, *a, __gmpfr_default_rounding_mode);
-         }
+         mpfr_atan2(*mpfr_t_obj, t, *a, __gmpfr_default_rounding_mode);
+       }
        else {
-         mpfr_atan2(*mpfr_t_obj, *a, *mpfr_t_obj, __gmpfr_default_rounding_mode);
-         }
+         mpfr_atan2(*mpfr_t_obj, *a, t, __gmpfr_default_rounding_mode);
+       }
        sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
+       mpfr_clear(t);
        SvREADONLY_on(obj);
        return obj_ref;
      }
 
      if(SvIOK(b)) {
-       mpfr_set_sj(*mpfr_t_obj, SvIV(b), __gmpfr_default_rounding_mode);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
+       mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
        if(third == &PL_sv_yes){
-         mpfr_atan2(*mpfr_t_obj, *mpfr_t_obj, *a, __gmpfr_default_rounding_mode);
-         }
+         mpfr_atan2(*mpfr_t_obj, t, *a, __gmpfr_default_rounding_mode);
+       }
        else {
-         mpfr_atan2(*mpfr_t_obj, *a, *mpfr_t_obj, __gmpfr_default_rounding_mode);
-         }
+         mpfr_atan2(*mpfr_t_obj, *a, t, __gmpfr_default_rounding_mode);
+       }
+       mpfr_clear(t);
        sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
        SvREADONLY_on(obj);
        return obj_ref;
@@ -4118,10 +4233,10 @@ SV * overload_atan2(pTHX_ mpfr_t * a, SV * b, SV * third) {
          croak("Invalid string supplied to Math::MPFR::overload_atan2");
        if(third == &PL_sv_yes){
          mpfr_atan2(*mpfr_t_obj, *mpfr_t_obj, *a, __gmpfr_default_rounding_mode);
-         }
+       }
        else {
          mpfr_atan2(*mpfr_t_obj, *a, *mpfr_t_obj, __gmpfr_default_rounding_mode);
-         }
+       }
        sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
        SvREADONLY_on(obj);
        return obj_ref;
@@ -4129,26 +4244,30 @@ SV * overload_atan2(pTHX_ mpfr_t * a, SV * b, SV * third) {
 #endif
 #else
      if(SvUOK(b)) {
-       mpfr_set_ui(*mpfr_t_obj, SvUV(b), __gmpfr_default_rounding_mode);
+       mpfr_init2(t, 8 * sizeof(long));
+       mpfr_set_ui(t, SvUV(b), __gmpfr_default_rounding_mode);
        if(third == &PL_sv_yes){
-         mpfr_atan2(*mpfr_t_obj, *mpfr_t_obj, *a, __gmpfr_default_rounding_mode);
-         }
+         mpfr_atan2(*mpfr_t_obj, t, *a, __gmpfr_default_rounding_mode);
+       }
        else {
-         mpfr_atan2(*mpfr_t_obj, *a, *mpfr_t_obj, __gmpfr_default_rounding_mode);
-         }
+         mpfr_atan2(*mpfr_t_obj, *a, t, __gmpfr_default_rounding_mode);
+       }
+       mpfr_clear(t);
        sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
        SvREADONLY_on(obj);
        return obj_ref;
      }
 
      if(SvIOK(b)) {
-       mpfr_set_si(*mpfr_t_obj, SvIV(b), __gmpfr_default_rounding_mode);
+       mpfr_init2(t, 8 * sizeof(long));
+       mpfr_set_si(t, SvIV(b), __gmpfr_default_rounding_mode);
        if(third == &PL_sv_yes){
-         mpfr_atan2(*mpfr_t_obj, *mpfr_t_obj, *a, __gmpfr_default_rounding_mode);
-         }
+         mpfr_atan2(*mpfr_t_obj, t, *a, __gmpfr_default_rounding_mode);
+       }
        else {
-         mpfr_atan2(*mpfr_t_obj, *a, *mpfr_t_obj, __gmpfr_default_rounding_mode);
-         }
+         mpfr_atan2(*mpfr_t_obj, *a, t, __gmpfr_default_rounding_mode);
+       }
+       mpfr_clear(t);
        sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
        SvREADONLY_on(obj);
        return obj_ref;
@@ -4156,21 +4275,25 @@ SV * overload_atan2(pTHX_ mpfr_t * a, SV * b, SV * third) {
 #endif
 
      if(SvNOK(b)) {
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       mpfr_set_ld(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#else
-       mpfr_set_d(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
+
+#if defined(CAN_PASS_FLOAT128)
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+#elif defined(USE_LONG_DOUBLE)
+       mpfr_init2(t, LDBL_MANT_DIG);
+       mpfr_set_ld(t, (long double)SvNV(b), __gmpfr_default_rounding_mode);
 #else
-       mpfr_set_d(*mpfr_t_obj, SvNV(b), __gmpfr_default_rounding_mode);
+       mpfr_init2(t, DBL_MANT_DIG);
+       mpfr_set_d(t, (double)SvNV(b), __gmpfr_default_rounding_mode);
 #endif
+
        if(third == &PL_sv_yes){
-         mpfr_atan2(*mpfr_t_obj, *mpfr_t_obj, *a, __gmpfr_default_rounding_mode);
-         }
+         mpfr_atan2(*mpfr_t_obj, t, *a, __gmpfr_default_rounding_mode);
+       }
        else {
-         mpfr_atan2(*mpfr_t_obj, *a, *mpfr_t_obj, __gmpfr_default_rounding_mode);
-         }
+         mpfr_atan2(*mpfr_t_obj, *a, t, __gmpfr_default_rounding_mode);
+       }
+       mpfr_clear(t);
        sv_setiv(obj, INT2PTR(IV,mpfr_t_obj));
        SvREADONLY_on(obj);
        return obj_ref;
@@ -4324,10 +4447,10 @@ SV * overload_pow_eq(pTHX_ SV * p, SV * second, SV * third) {
 
      SvREFCNT_inc(p);
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(second)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_uj(t, SvUV(second), __gmpfr_default_rounding_mode);
        mpfr_pow(*(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
@@ -4335,7 +4458,7 @@ SV * overload_pow_eq(pTHX_ SV * p, SV * second, SV * third) {
      }
 
      if(SvIOK(second)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_sj(t, SvIV(second), __gmpfr_default_rounding_mode);
        mpfr_pow(*(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
@@ -4359,26 +4482,30 @@ SV * overload_pow_eq(pTHX_ SV * p, SV * second, SV * third) {
      }
 
      if(SvIOK(second)) {
+       /*
        if(SvIV(second) >= 0) {
          mpfr_pow_ui(*(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), SvUV(second), __gmpfr_default_rounding_mode);
          return p;
        }
+       */
        mpfr_pow_si(*(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), SvIV(second), __gmpfr_default_rounding_mode);
        return p;
      }
 #endif
 
      if(SvNOK(second)) {
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       mpfr_init(t);
-       mpfr_set_ld(t, SvNV(second), __gmpfr_default_rounding_mode);
-#else
-       mpfr_init_set_d(t, SvNV(second), __gmpfr_default_rounding_mode);
-#endif
+
+#if defined(CAN_PASS_FLOAT128)
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(second), __gmpfr_default_rounding_mode);
+#elif defined(USE_LONG_DOUBLE)
+       mpfr_init2(t, LDBL_MANT_DIG);
+       mpfr_set_ld(t, (long double)SvNV(second), __gmpfr_default_rounding_mode);
 #else
-       mpfr_init_set_d(t, SvNV(second), __gmpfr_default_rounding_mode);
+       mpfr_init2(t, DBL_MANT_DIG);
+       mpfr_set_d(t, (double)SvNV(second), __gmpfr_default_rounding_mode);
 #endif
+
        mpfr_pow(*(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
        return p;
@@ -4406,7 +4533,7 @@ SV * overload_pow_eq(pTHX_ SV * p, SV * second, SV * third) {
          return p;
        }
        if(strEQ(h, "Math::GMPf")) {
-         mpfr_init(t);
+         mpfr_init2(t, (mpfr_prec_t)mpf_get_prec(*(INT2PTR(mpf_t *, SvIV(SvRV(second))))));
          mpfr_set_f(t, *(INT2PTR(mpf_t *, SvIV(SvRV(second)))), __gmpfr_default_rounding_mode);
          mpfr_pow(*(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(p)))), t, __gmpfr_default_rounding_mode);
          mpfr_clear(t);
@@ -4430,10 +4557,10 @@ SV * overload_div_eq(pTHX_ SV * a, SV * b, SV * third) {
 
      SvREFCNT_inc(a);
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
        mpfr_div(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
@@ -4441,7 +4568,7 @@ SV * overload_div_eq(pTHX_ SV * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
        mpfr_div(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
@@ -4465,6 +4592,9 @@ SV * overload_div_eq(pTHX_ SV * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
+       mpfr_div_si(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b), __gmpfr_default_rounding_mode);
+       return a;
+       /*
        if(SvIV(b) >= 0) {
          mpfr_div_ui(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvUV(b), __gmpfr_default_rounding_mode);
          return a;
@@ -4472,20 +4602,28 @@ SV * overload_div_eq(pTHX_ SV * a, SV * b, SV * third) {
        mpfr_div_ui(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b) * -1, __gmpfr_default_rounding_mode);
        mpfr_neg(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
        return a;
+       */
      }
 #endif
 
      if(SvNOK(b)) {
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       mpfr_init(t);
-       mpfr_set_ld(t, SvNV(b), __gmpfr_default_rounding_mode);
-#else
-       mpfr_init_set_d(t, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
+
+#if defined(CAN_PASS_FLOAT128)
+
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+
+#elif defined(USE_LONG_DOUBLE)
+
+       mpfr_init2(t, LDBL_MANT_DIG);
+       mpfr_set_ld(t, (long double)SvNV(b), __gmpfr_default_rounding_mode);
+
 #else
-       mpfr_init_set_d(t, SvNV(b), __gmpfr_default_rounding_mode);
+
+       mpfr_init2(t, DBL_MANT_DIG);
+       mpfr_set_d(t, (double)SvNV(b), __gmpfr_default_rounding_mode);
 #endif
+
        mpfr_div(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
        return a;
@@ -4513,7 +4651,7 @@ SV * overload_div_eq(pTHX_ SV * a, SV * b, SV * third) {
          return a;
        }
        if(strEQ(h, "Math::GMPf")) {
-         mpfr_init(t);
+         mpfr_init2(t, (mpfr_prec_t)mpf_get_prec(*(INT2PTR(mpf_t *, SvIV(SvRV(b))))));
          mpfr_set_f(t, *(INT2PTR(mpf_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
          mpfr_div(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
          mpfr_clear(t);
@@ -4534,10 +4672,10 @@ SV * overload_sub_eq(pTHX_ SV * a, SV * b, SV * third) {
 
      SvREFCNT_inc(a);
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
        mpfr_sub(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
@@ -4545,7 +4683,7 @@ SV * overload_sub_eq(pTHX_ SV * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
        mpfr_sub(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
@@ -4569,26 +4707,38 @@ SV * overload_sub_eq(pTHX_ SV * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
+       mpfr_sub_si(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b), __gmpfr_default_rounding_mode);
+       return a;
+       /*
        if(SvIV(b) >= 0) {
          mpfr_sub_ui(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvUV(b), __gmpfr_default_rounding_mode);
          return a;
        }
        mpfr_add_ui(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b) * -1, __gmpfr_default_rounding_mode);
        return a;
+       */
      }
 #endif
 
      if(SvNOK(b)) {
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       mpfr_init(t);
-       mpfr_set_ld(t, SvNV(b), __gmpfr_default_rounding_mode);
-#else
-       mpfr_init_set_d(t, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
+
+#if defined(CAN_PASS_FLOAT128)
+
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+
+#elif defined(USE_LONG_DOUBLE)
+
+       mpfr_init2(t, LDBL_MANT_DIG);
+       mpfr_set_ld(t, (long double)SvNV(b), __gmpfr_default_rounding_mode);
+
 #else
-       mpfr_init_set_d(t, SvNV(b), __gmpfr_default_rounding_mode);
+
+       mpfr_init2(t, DBL_MANT_DIG);
+       mpfr_init_set_d(t, (double)SvNV(b), __gmpfr_default_rounding_mode);
+
 #endif
+
        mpfr_sub(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
        return a;
@@ -4616,7 +4766,7 @@ SV * overload_sub_eq(pTHX_ SV * a, SV * b, SV * third) {
          return a;
        }
        if(strEQ(h, "Math::GMPf")) {
-         mpfr_init(t);
+         mpfr_init2(t, (mpfr_prec_t)mpf_get_prec(*(INT2PTR(mpf_t *, SvIV(SvRV(b))))));
          mpfr_set_f(t, *(INT2PTR(mpf_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
          mpfr_sub(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
          mpfr_clear(t);
@@ -4637,10 +4787,10 @@ SV * overload_add_eq(pTHX_ SV * a, SV * b, SV * third) {
 
      SvREFCNT_inc(a);
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
        mpfr_add(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
@@ -4648,7 +4798,7 @@ SV * overload_add_eq(pTHX_ SV * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
        mpfr_add(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
@@ -4672,26 +4822,38 @@ SV * overload_add_eq(pTHX_ SV * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
+       mpfr_add_si(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b), __gmpfr_default_rounding_mode);
+       return a;
+       /*
        if(SvIV(b) >= 0) {
          mpfr_add_ui(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvUV(b), __gmpfr_default_rounding_mode);
          return a;
        }
        mpfr_sub_ui(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b) * -1, __gmpfr_default_rounding_mode);
        return a;
+       */
      }
 #endif
 
      if(SvNOK(b)) {
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       mpfr_init(t);
-       mpfr_set_ld(t, SvNV(b), __gmpfr_default_rounding_mode);
-#else
-       mpfr_init_set_d(t, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
+
+#if defined(CAN_PASS_FLOAT128)
+
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+
+#elif defined(USE_LONG_DOUBLE)
+
+       mpfr_init2(t, LDBL_MANT_DIG);
+       mpfr_set_ld(t, (long double)SvNV(b), __gmpfr_default_rounding_mode);
+
 #else
-       mpfr_init_set_d(t, SvNV(b), __gmpfr_default_rounding_mode);
+
+       mpfr_init2(t, DBL_MANT_DIG);
+       mpfr_set_d(t, (double)SvNV(b), __gmpfr_default_rounding_mode);
+
 #endif
+
        mpfr_add(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
        return a;
@@ -4719,7 +4881,7 @@ SV * overload_add_eq(pTHX_ SV * a, SV * b, SV * third) {
          return a;
        }
        if(strEQ(h, "Math::GMPf")) {
-         mpfr_init(t);
+         mpfr_init2(t, (mpfr_prec_t)mpf_get_prec(*(INT2PTR(mpf_t *, SvIV(SvRV(b))))));
          mpfr_set_f(t, *(INT2PTR(mpf_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
          mpfr_add(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
          mpfr_clear(t);
@@ -4740,10 +4902,10 @@ SV * overload_mul_eq(pTHX_ SV * a, SV * b, SV * third) {
 
      SvREFCNT_inc(a);
 
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
 #ifndef _MSC_VER
      if(SvUOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_uj(t, SvUV(b), __gmpfr_default_rounding_mode);
        mpfr_mul(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
@@ -4751,7 +4913,7 @@ SV * overload_mul_eq(pTHX_ SV * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
-       mpfr_init(t);
+       mpfr_init2(t, (mpfr_prec_t)IVSIZE_BITS);
        mpfr_set_sj(t, SvIV(b), __gmpfr_default_rounding_mode);
        mpfr_mul(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
@@ -4775,6 +4937,9 @@ SV * overload_mul_eq(pTHX_ SV * a, SV * b, SV * third) {
      }
 
      if(SvIOK(b)) {
+       mpfr_mul_si(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b), __gmpfr_default_rounding_mode);
+       return a;
+       /*
        if(SvIV(b) >= 0) {
          mpfr_mul_ui(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvUV(b), __gmpfr_default_rounding_mode);
          return a;
@@ -4782,20 +4947,29 @@ SV * overload_mul_eq(pTHX_ SV * a, SV * b, SV * third) {
        mpfr_mul_ui(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), SvIV(b) * -1, __gmpfr_default_rounding_mode);
        mpfr_neg(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), __gmpfr_default_rounding_mode);
        return a;
+       */
      }
 #endif
 
      if(SvNOK(b)) {
-#ifdef USE_LONG_DOUBLE
-#ifndef _MSC_VER
-       mpfr_init(t);
-       mpfr_set_ld(t, SvNV(b), __gmpfr_default_rounding_mode);
-#else
-       mpfr_init_set_d(t, SvNV(b), __gmpfr_default_rounding_mode);
-#endif
+
+#if defined(CAN_PASS_FLOAT128)
+
+       mpfr_init2(t, FLT128_MANT_DIG);
+       mpfr_set_float128(t, (float128)SvNV(b), __gmpfr_default_rounding_mode);
+
+#elif defined(USE_LONG_DOUBLE)
+
+       mpfr_init2(t, LDBL_MANT_DIG);
+       mpfr_set_ld(t, (long double)SvNV(b), __gmpfr_default_rounding_mode);
+
 #else
-       mpfr_init_set_d(t, SvNV(b), __gmpfr_default_rounding_mode);
+
+       mpfr_init2(t, DBL_MANT_DIG);
+       mpfr_init_set_d(t, (double)SvNV(b), __gmpfr_default_rounding_mode);
+
 #endif
+
        mpfr_mul(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
        mpfr_clear(t);
        return a;
@@ -4823,7 +4997,7 @@ SV * overload_mul_eq(pTHX_ SV * a, SV * b, SV * third) {
          return a;
        }
        if(strEQ(h, "Math::GMPf")) {
-         mpfr_init(t);
+         mpfr_init2(t, (mpfr_prec_t)mpf_get_prec(*(INT2PTR(mpf_t *, SvIV(SvRV(b))))));
          mpfr_set_f(t, *(INT2PTR(mpf_t *, SvIV(SvRV(b)))), __gmpfr_default_rounding_mode);
          mpfr_mul(*(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), *(INT2PTR(mpfr_t *, SvIV(SvRV(a)))), t, __gmpfr_default_rounding_mode);
          mpfr_clear(t);
@@ -4856,7 +5030,7 @@ SV * _itsa(pTHX_ SV * a) {
 }
 
 int _has_longlong(void) {
-#ifdef USE_64_BIT_INT
+#ifdef MATH_MPFR_NEED_LONG_LONG_INT
     return 1;
 #else
     return 0;
@@ -4871,6 +5045,14 @@ int _has_longdouble(void) {
 #endif
 }
 
+int _ivsize_bits(void) {
+   int ret = 0;
+#ifdef IVSIZE_BITS
+   ret = IVSIZE_BITS;
+#endif
+   return ret;
+}
+
 /*
 int _mpfr_longsize(void) {
     mpfr_t x, y;
@@ -5398,9 +5580,9 @@ SV * Rmpfr_set_LD(pTHX_ mpfr_t * rop, SV * op, SV *rnd) {
 int mpfr_set_decimal64 (mpfr_t rop, _Decimal64 op, mpfr_rnd_t rnd)
 */
 
-SV * Rmpfr_set_decimal64(pTHX_ mpfr_t * rop, SV * op, SV * rnd) {
+SV * Rmpfr_set_DECIMAL64(pTHX_ mpfr_t * rop, SV * op, SV * rnd) {
 #if (!defined(MPFR_VERSION) || (MPFR_VERSION<MPFR_VERSION_NUM(3,1,0)))
-     croak("Perl interface to Rmpfr_set_decimal64 not available for this version (%s) of the mpfr library. We need at least version 3.1.0",
+     croak("Perl interface to Rmpfr_set_DECIMAL64 not available for this version (%s) of the mpfr library. We need at least version 3.1.0",
             MPFR_VERSION_STRING);
 #endif
 
@@ -5415,10 +5597,10 @@ SV * Rmpfr_set_decimal64(pTHX_ mpfr_t * rop, SV * op, SV * rnd) {
 
       if(strEQ(h, "Math::Decimal64"))
         return newSViv(mpfr_set_decimal64(*rop, *(INT2PTR(_Decimal64 *, SvIV(SvRV(op)))), (mp_rnd_t)SvUV(rnd)));
-       croak("2nd arg (a %s object) supplied to Rmpfr_set_decimal64 needs to be a Math::Decimal64 object",
+       croak("2nd arg (a %s object) supplied to Rmpfr_set_DECIMAL64 needs to be a Math::Decimal64 object",
                HvNAME(SvSTASH(SvRV(op))));
     }
-    else croak("2nd arg (which needs to be a Math::Decimal64 object) supplied to Rmpfr_set_decimal64 is not an object");
+    else croak("2nd arg (which needs to be a Math::Decimal64 object) supplied to Rmpfr_set_DECIMAL64 is not an object");
 
 #else
 
@@ -5440,9 +5622,9 @@ void Rmpfr_get_LD(pTHX_ SV * rop, mpfr_t * op, SV * rnd) {
      else croak("1st arg (which needs to be a Math::LongDouble object) supplied to Rmpfr_get_LD is not an object");
 }
 
-void Rmpfr_get_decimal64(pTHX_ SV * rop, mpfr_t * op, SV * rnd) {
+void Rmpfr_get_DECIMAL64(pTHX_ SV * rop, mpfr_t * op, SV * rnd) {
 #if (!defined(MPFR_VERSION) || (MPFR_VERSION<MPFR_VERSION_NUM(3,1,0)))
-     croak("Perl interface to Rmpfr_get_decimal64 not available for this version (%s) of the mpfr library. We need at least version 3.1.0",
+     croak("Perl interface to Rmpfr_get_DECIMAL64 not available for this version (%s) of the mpfr library. We need at least version 3.1.0",
               MPFR_VERSION_STRING);
 #endif
 
@@ -5458,10 +5640,10 @@ void Rmpfr_get_decimal64(pTHX_ SV * rop, mpfr_t * op, SV * rnd) {
       if(strEQ(h, "Math::Decimal64"))
         *(INT2PTR(_Decimal64 *, SvIV(SvRV(rop)))) = mpfr_get_decimal64(*op, (mp_rnd_t)SvUV(rnd));
 
-       else croak("1st arg (a %s object) supplied to Rmpfr_get_decimal64 needs to be a Math::Decimal64 object",
+       else croak("1st arg (a %s object) supplied to Rmpfr_get_DECIMAL64 needs to be a Math::Decimal64 object",
                       HvNAME(SvSTASH(SvRV(rop))));
     }
-    else croak("1st arg (which needs to be a Math::Decimal64 object) supplied to Rmpfr_get_decimal64 is not an object");
+    else croak("1st arg (which needs to be a Math::Decimal64 object) supplied to Rmpfr_get_DECIMAL64 is not an object");
 
 #else
 
@@ -5514,6 +5696,14 @@ SV * _nvsize(pTHX) {
      return newSVuv(sizeof(NV));
 }
 
+SV * _FLT128_DIG(pTHX) {
+#ifdef FLT128_DIG
+     return newSViv(FLT128_DIG);
+#else
+     return &PL_sv_undef;
+#endif
+}
+
 SV * _LDBL_DIG(pTHX) {
 #ifdef LDBL_DIG
      return newSViv(LDBL_DIG);
@@ -5530,6 +5720,14 @@ SV * _DBL_DIG(pTHX) {
 #endif
 }
 
+SV * _FLT128_MANT_DIG(pTHX) {
+#ifdef FLT128_MANT_DIG
+     return newSViv(FLT128_MANT_DIG);
+#else
+     return &PL_sv_undef;
+#endif
+}
+
 SV * _LDBL_MANT_DIG(pTHX) {
 #ifdef LDBL_MANT_DIG
      return newSViv(LDBL_MANT_DIG);
@@ -5634,9 +5832,18 @@ SV * Rgmp_randinit_lc_2exp_size(pTHX_ SV * size) {
 /***********************************************
 ************************************************/
 
-void Rmpfr_get_float128(pTHX_ SV * rop, mpfr_t * op, SV * rnd) {
-#if (!defined(MPFR_VERSION) || (MPFR_VERSION<MPFR_VERSION_NUM(3,2,0)))
-     croak("Perl interface to Rmpfr_get_float128 not available for this version (%s) of the mpfr library. We need at least version 3.2.0",
+SV * Rmpfr_get_float128(pTHX_ mpfr_t * op, SV * rnd) {
+
+#ifdef CAN_PASS_FLOAT128
+     return newSVnv(mpfr_get_float128(*op, (mp_rnd_t)SvUV(rnd)));
+#else
+     croak("Cannot use Rmpfr_get_float128 to return an NV");
+#endif
+}
+
+void Rmpfr_get_FLOAT128(pTHX_ SV * rop, mpfr_t * op, SV * rnd) {
+#if (!defined(MPFR_VERSION) || (MPFR_VERSION < MPFR_VERSION_NUM(3,2,0)))
+     croak("Perl interface to Rmpfr_get_FLOAT128 not available for this version (%s) of the mpfr library. We need at least version 3.2.0",
               MPFR_VERSION_STRING);
 #endif
 
@@ -5652,10 +5859,10 @@ void Rmpfr_get_float128(pTHX_ SV * rop, mpfr_t * op, SV * rnd) {
       if(strEQ(h, "Math::Float128"))
         *(INT2PTR(float128 *, SvIV(SvRV(rop)))) = mpfr_get_float128(*op, (mp_rnd_t)SvUV(rnd));
 
-       else croak("1st arg (a %s object) supplied to Rmpfr_get_float128 needs to be a Math::Float128 object",
+       else croak("1st arg (a %s object) supplied to Rmpfr_get_FLOAT128 needs to be a Math::Float128 object",
                       HvNAME(SvSTASH(SvRV(rop))));
     }
-    else croak("1st arg (which needs to be a Math::Float128 object) supplied to Rmpfr_get_float128 is not an object");
+    else croak("1st arg (which needs to be a Math::Float128 object) supplied to Rmpfr_get_FLOAT128 is not an object");
 
 #else
 
@@ -5664,9 +5871,9 @@ void Rmpfr_get_float128(pTHX_ SV * rop, mpfr_t * op, SV * rnd) {
 #endif
 }
 
-SV * Rmpfr_set_float128(pTHX_ mpfr_t * rop, SV * op, SV * rnd) {
-#if (!defined(MPFR_VERSION) || (MPFR_VERSION<MPFR_VERSION_NUM(3,2,0)))
-     croak("Perl interface to Rmpfr_set_float128 not available for this version (%s) of the mpfr library. We need at least version 3.2.0",
+SV * Rmpfr_set_FLOAT128(pTHX_ mpfr_t * rop, SV * op, SV * rnd) {
+#if (!defined(MPFR_VERSION) || (MPFR_VERSION < MPFR_VERSION_NUM(3,2,0)))
+     croak("Perl interface to Rmpfr_set_FLOAT128 not available for this version (%s) of the mpfr library. We need at least version 3.2.0",
             MPFR_VERSION_STRING);
 #endif
 
@@ -5681,10 +5888,10 @@ SV * Rmpfr_set_float128(pTHX_ mpfr_t * rop, SV * op, SV * rnd) {
 
       if(strEQ(h, "Math::Float128"))
         return newSViv(mpfr_set_float128(*rop, *(INT2PTR(float128 *, SvIV(SvRV(op)))), (mp_rnd_t)SvUV(rnd)));
-       croak("2nd arg (a %s object) supplied to Rmpfr_set_float128 needs to be a Math::Float128 object",
+       croak("2nd arg (a %s object) supplied to Rmpfr_set_FLOAT128 needs to be a Math::Float128 object",
                HvNAME(SvSTASH(SvRV(op))));
     }
-    else croak("2nd arg (which needs to be a Math::Float128 object) supplied to Rmpfr_set_float128 is not an object");
+    else croak("2nd arg (which needs to be a Math::Float128 object) supplied to Rmpfr_set_FLOAT128 is not an object");
 
 #else
 
@@ -5693,6 +5900,16 @@ SV * Rmpfr_set_float128(pTHX_ mpfr_t * rop, SV * op, SV * rnd) {
 #endif
 }
 
+SV * Rmpfr_set_float128(pTHX_ mpfr_t * rop, SV * q, SV * rnd) {
+
+#ifdef CAN_PASS_FLOAT128
+     return newSViv(mpfr_set_float128(*rop, (float128)SvNV(q), (mp_rnd_t)SvUV(rnd)));
+#else
+     croak("Cannot use Rmpfr_set_float128 to set an NV");
+#endif
+
+}
+
 SV * _is_readonly(pTHX_ SV * sv) {
      if SvREADONLY(sv) return newSVuv(1);
      return newSVuv(0);
@@ -5706,6 +5923,25 @@ void _readonly_off(pTHX_ SV * sv) {
      SvREADONLY_off(sv);
 }
 
+int _can_pass_float128(void) {
+
+#ifdef CAN_PASS_FLOAT128
+   return 1;
+#else
+   return 0;
+#endif
+
+}
+
+int _mpfr_want_float128(void) {
+
+#ifdef MPFR_WANT_FLOAT128
+   return 1;
+#else
+   return 0;
+#endif
+
+}
 
 
 MODULE = Math::MPFR  PACKAGE = Math::MPFR
@@ -8965,6 +9201,10 @@ int
 _has_longdouble ()
 
 
+int
+_ivsize_bits ()
+
+
 SV *
 RMPFR_PREC_MAX ()
 CODE:
@@ -9276,12 +9516,12 @@ CODE:
 OUTPUT:  RETVAL
 
 SV *
-Rmpfr_set_decimal64 (rop, op, rnd)
+Rmpfr_set_DECIMAL64 (rop, op, rnd)
 	mpfr_t *	rop
 	SV *	op
 	SV *	rnd
 CODE:
-  RETVAL = Rmpfr_set_decimal64 (aTHX_ rop, op, rnd);
+  RETVAL = Rmpfr_set_DECIMAL64 (aTHX_ rop, op, rnd);
 OUTPUT:  RETVAL
 
 void
@@ -9303,7 +9543,7 @@ Rmpfr_get_LD (rop, op, rnd)
         return; /* assume stack size is correct */
 
 void
-Rmpfr_get_decimal64 (rop, op, rnd)
+Rmpfr_get_DECIMAL64 (rop, op, rnd)
 	SV *	rop
 	mpfr_t *	op
 	SV *	rnd
@@ -9311,7 +9551,7 @@ Rmpfr_get_decimal64 (rop, op, rnd)
         I32* temp;
         PPCODE:
         temp = PL_markstack_ptr++;
-        Rmpfr_get_decimal64(aTHX_ rop, op, rnd);
+        Rmpfr_get_DECIMAL64(aTHX_ rop, op, rnd);
         if (PL_markstack_ptr != temp) {
           /* truly void, because dXSARGS not invoked */
           PL_markstack_ptr = temp;
@@ -9373,6 +9613,13 @@ OUTPUT:  RETVAL
 
 
 SV *
+_FLT128_DIG ()
+CODE:
+  RETVAL = _FLT128_DIG (aTHX);
+OUTPUT:  RETVAL
+
+
+SV *
 _LDBL_DIG ()
 CODE:
   RETVAL = _LDBL_DIG (aTHX);
@@ -9387,6 +9634,13 @@ OUTPUT:  RETVAL
 
 
 SV *
+_FLT128_MANT_DIG ()
+CODE:
+  RETVAL = _FLT128_MANT_DIG (aTHX);
+OUTPUT:  RETVAL
+
+
+SV *
 _LDBL_MANT_DIG ()
 CODE:
   RETVAL = _LDBL_MANT_DIG (aTHX);
@@ -9430,8 +9684,16 @@ CODE:
   RETVAL = Rgmp_randinit_lc_2exp_size (aTHX_ size);
 OUTPUT:  RETVAL
 
+SV *
+Rmpfr_get_float128 (op, rnd)
+	mpfr_t *	op
+	SV *	rnd
+CODE:
+  RETVAL = Rmpfr_get_float128 (aTHX_ op, rnd);
+OUTPUT:  RETVAL
+
 void
-Rmpfr_get_float128 (rop, op, rnd)
+Rmpfr_get_FLOAT128 (rop, op, rnd)
 	SV *	rop
 	mpfr_t *	op
 	SV *	rnd
@@ -9439,7 +9701,7 @@ Rmpfr_get_float128 (rop, op, rnd)
         I32* temp;
         PPCODE:
         temp = PL_markstack_ptr++;
-        Rmpfr_get_float128(aTHX_ rop, op, rnd);
+        Rmpfr_get_FLOAT128(aTHX_ rop, op, rnd);
         if (PL_markstack_ptr != temp) {
           /* truly void, because dXSARGS not invoked */
           PL_markstack_ptr = temp;
@@ -9449,12 +9711,21 @@ Rmpfr_get_float128 (rop, op, rnd)
         return; /* assume stack size is correct */
 
 SV *
-Rmpfr_set_float128 (rop, op, rnd)
+Rmpfr_set_FLOAT128 (rop, op, rnd)
 	mpfr_t *	rop
 	SV *	op
 	SV *	rnd
 CODE:
-  RETVAL = Rmpfr_set_float128 (aTHX_ rop, op, rnd);
+  RETVAL = Rmpfr_set_FLOAT128 (aTHX_ rop, op, rnd);
+OUTPUT:  RETVAL
+
+SV *
+Rmpfr_set_float128 (rop, q, rnd)
+	mpfr_t *	rop
+	SV *	q
+	SV *	rnd
+CODE:
+  RETVAL = Rmpfr_set_float128 (aTHX_ rop, q, rnd);
 OUTPUT:  RETVAL
 
 SV *
@@ -9496,3 +9767,11 @@ _readonly_off (sv)
         /* must have used dXSARGS; list context implied */
         return; /* assume stack size is correct */
 
+int
+_can_pass_float128 ()
+
+
+int
+_mpfr_want_float128 ()
+
+
@@ -20,17 +20,25 @@ for(@ARGV) {
   $have_decimal64 = 1 if $_ eq 'D64=1';
 }
 #$have_decimal64 = 1; # Force inclusion of _Decimal64 support
-                      # This will also define MPFR_WANT_DECIMAL_FLOATS
+                      # This will also define MPFR_WANT_DECIMAL_FLOATS (as that needs to be defined
+                      # before mpfr.h is included).
 
 my $d64_message = $have_decimal64 ? "Attempting to build with _Decimal64 support\n"
                                   : "Building without _Decimal64 support\n";
 
+# We want to set $have_float128 to 1 if and only if:
+# the mpfr library was built with the configure option '--enable-float128' && either:
+#  $Config{nvtype} is '__float128'
+#   or
+#  Math::Float128 has been installed.
+
 $have_float128 = 0;
 for(@ARGV) {
   $have_float128 = 1 if $_ eq 'F128=1';
 }
 #$have_float128 = 1; # Force inclusion of __float128 support
-                      # This will also define MPFR_WANT_FLOAT128
+                      # This will also define MPFR_WANT_FLOAT128 (as that needs to be defined
+                      # before mpfr.h is included).
 
 my $float128_message = $have_float128 ? "Attempting to build with __float128 support\n"
                                   : "Building without __float128 support\n";
@@ -38,10 +46,10 @@ my $float128_message = $have_float128 ? "Attempting to build with __float128 sup
 my $defines = $] < 5.008 ? "-DOLDPERL" : "-DNEWPERL";
 
 if($use_64_bit_int == -1) {}
-elsif($use_64_bit_int == 1) {$defines .= " -DUSE_64_BIT_INT"}
+elsif($use_64_bit_int == 1) {$defines .= " -DMATH_MPFR_NEED_LONG_LONG_INT -DIVSIZE_BITS=" . (8 * $Config{ivsize})}
 else {
-  unless($Config::Config{ivsize} < 8) {
-    $defines .= " -DUSE_64_BIT_INT";
+  unless($Config{ivsize} < 8 || $Config{ivtype} eq 'long') {
+    $defines .= " -DMATH_MPFR_NEED_LONG_LONG_INT -DIVSIZE_BITS=" . (8 * $Config{ivsize});
   }
 }
 
@@ -55,11 +63,13 @@ else {
 
 $defines .= " -DMPFR_WANT_DECIMAL_FLOATS" if $have_decimal64;
 $defines .= " -DMPFR_WANT_FLOAT128" if $have_float128;
+$defines .= " -DNV_IS_FLOAT128" if $Config{nvtype} eq '__float128';
+$defines .= " -DNV_IS_LONG_DOUBLE" if $Config{nvtype} eq 'long double';
 
 print "\nThis module requires the following C libraries:\n";
 print " gmp-4.2.0 (or later)\n mpfr-2.4.0 (or later)\n\n";
-$defines =~ /-DUSE_64_BIT_INT/ ? print "Building with 64-bit'long long' support\n" :
-                                 print "Building without 64-bit 'long long' support\n";
+$defines =~ /-DMATH_MPFR_NEED_LONG_LONG_INT/ ? print "Building with 'long long' support\n" :
+                                 print "Building without 'long long' support\n";
 
 print "If this is wrong, see the \"64-bit support\" section in the README\n\n";
 
@@ -99,7 +109,7 @@ my %options = (
 
 my %prereq = ();
 $prereq{'Math::Decimal64'} = '0.01' if $have_decimal64;
-$prereq{'Math::Float128'}  = '0.01' if $have_float128;
+$prereq{'Math::Float128'}  = '0.01' if ($have_float128 && $Config{nvtype} ne '__float128');
 
 $options{PREREQ_PM} = \%prereq;
 
@@ -1,4 +1,4 @@
-## This file generated by InlineX::C2XS (version 0.22) using Inline::C (version 0.5301)
+## This file generated by InlineX::C2XS (version 0.24) using Inline::C (version 0.62_13)
 package Math::MPFR::Prec;
 use strict;
 use warnings;
@@ -7,9 +7,9 @@ require Exporter;
 *import = \&Exporter::import;
 require DynaLoader;
 
-$Math::MPFR::Prec::VERSION = '3.22';
-
-DynaLoader::bootstrap Math::MPFR::Prec $Math::MPFR::Prec::VERSION;
+our $VERSION = '3.23';
+$VERSION = eval $VERSION;
+DynaLoader::bootstrap Math::MPFR::Prec $VERSION;
 
 @Math::MPFR::Prec::EXPORT = ();
 @Math::MPFR::Prec::EXPORT_OK = ();
@@ -53,23 +53,27 @@ 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) and F128=1 (for __float128 support).
+See the Decimal64 and Float128 sections (below).
+
 ==================================
 64-bit-int and long double support
 ==================================
 
 If your perl's Config reports that 'ivsize' is greater than or
-equal to 8, then Math::MPFR will, by default, be built with access
-to the mpfr_*_uj and mpfr_*_sj functions. Else, access to those
-functions is, by default, denied. You can override the default by
-opening up the Makefile.PL and uncommenting the appropriate line (just
-a few lines down from the top of the file ... the comments in that
-file should make it clear).
+equal to 8 && 'ivtype' is not 'long', then Math::MPFR will, by default,
+be built with access to the mpfr_*_uj and mpfr_*_sj functions. Else,
+access to those functions is, by default, denied. You can override the
+default by opening up the Makefile.PL and uncommenting the appropriate
+line (just a few lines down from the top of the file ... the comments
+in that file should make it clear).
 
 Similarly, if your perl's Config reports that 'nvsize' is greater than
-8 then Math::MPFR will, by default, be built with access
-to the mpfr_*_ld functions. Else, access to those functions is,
-by default, denied. Again, you can override the default by opening up the
-Makefile.PL and uncommenting the appropriate line.
+8 then Math::MPFR will, be built with access to the mpfr_*_ld functions.
+Else, access to those functions is, by default, denied. Again, you can
+override the default by opening up the Makefile.PL and uncommenting the
+appropriate line.
 
 I believe it to be both unnecessary and inadvisable to override the
 default - but if you do find that you need to override the default,
@@ -104,15 +108,17 @@ achieved by leaving $have_decimal64 set to zero.
 Conversion between Math::Float128 and Math::MPFR objects
 =========================================================
 
-The functions Rmpfr_set_float128 and Rmpfr_get_float128 allow
+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.
 Then you need to build and install Math::Float128.
-You'll also need to have the mpfr library (version 3.1.1 at least)
+You'll also need to have the mpfr library (version 3.2.0 at least)
 configured to handle the __float128-mpfr_t conversions. See the mpfr
-documentation for details of that aspect.
+documentation for details of that aspect. (It's just a matter of
+providing Configure with the --enable-float128 option when building
+mpfr-3.2.0 or later.)
 
 If those pre-conditions are met, you also need to provide F128=1
 as a command line argument to 'perl Makefile.PL'. (Altenatively you
@@ -137,4 +143,30 @@ and Math::MPFR objects:
 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 'double'.
+nvtype is other than 'long double'.
+
+=======================================================
+Conversion between __float128 NV and Math::MPFR objects
+=======================================================
+
+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 3.2.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.
+
+However, for that to work, you also need to have built Math::MPFR
+by starting with:
+
+  perl Makefile.PL F128=1
+
+(Altenatively you could edit the Makefile.PL before building
+Math::MPFR and set its $have_float128 variable to 1.)
+
+
@@ -1,4 +1,4 @@
-## This file generated by InlineX::C2XS (version 0.22) using Inline::C (version 0.5301)
+## This file generated by InlineX::C2XS (version 0.24) using Inline::C (version 0.62_13)
 package Math::MPFR::V;
 use strict;
 use warnings;
@@ -7,9 +7,9 @@ require Exporter;
 *import = \&Exporter::import;
 require DynaLoader;
 
-$Math::MPFR::V::VERSION = '3.22';
-
-DynaLoader::bootstrap Math::MPFR::V $Math::MPFR::V::VERSION;
+our $VERSION = '3.23';
+$VERSION = eval $VERSION;
+DynaLoader::bootstrap Math::MPFR::V $VERSION;
 
 @Math::MPFR::V::EXPORT = ();
 @Math::MPFR::V::EXPORT_OK = ();
@@ -47,7 +47,7 @@ unless($why) {
 
     my $fr = Math::MPFR->new($fr_arg, 10);
 
-    Rmpfr_get_decimal64($d64_1, $fr, $round);
+    Rmpfr_get_DECIMAL64($d64_1, $fr, $round);
     Rmpfr_get_LD($ld, $fr, $round);
     LDtoD64($d64_2, $ld);
 
@@ -71,8 +71,8 @@ unless($why) {
     my $eps = Math::Decimal64->new(1, -398);
     my $eps_ret = Math::Decimal64->new(2.5);
     my $eps_fr = Rmpfr_init2($_);
-    Rmpfr_set_decimal64($eps_fr, $eps, MPFR_RNDN);
-    Rmpfr_get_decimal64($eps_ret, $eps_fr, MPFR_RNDN);
+    Rmpfr_set_DECIMAL64($eps_fr, $eps, MPFR_RNDN);
+    Rmpfr_get_DECIMAL64($eps_ret, $eps_fr, MPFR_RNDN);
     unless($eps_ret == $eps) {
       warn "\nMPFR precision: ", Rmpfr_get_prec($eps_fr), "\n";
       warn "\$eps: $eps\n\$eps_ret: $eps_ret\n";
@@ -3,7 +3,7 @@ use strict;
 use Config;
 use Math::MPFR qw(:mpfr);
 
-print "1..4\n";
+print "1..5\n";
 
 print STDERR "\n# Using Math::MPFR version ", $Math::MPFR::VERSION, "\n";
 print STDERR "# Using mpfr library version ", MPFR_VERSION_STRING, "\n";
@@ -14,10 +14,10 @@ elsif(pack("L", 305419897) eq pack("V", 305419897)) {warn "# Machine appears to
 
 warn "# Byte Order: ", $Config{byteorder}, "\n";
 
-if($Math::MPFR::VERSION eq '3.22') {print "ok 1\n"}
+if($Math::MPFR::VERSION eq '3.23') {print "ok 1\n"}
 else {print "not ok 1 $Math::MPFR::VERSION\n"}
 
-if(Math::MPFR::_get_xs_version() eq '3.22') {print "ok 2\n"}
+if(Math::MPFR::_get_xs_version() eq '3.23') {print "ok 2\n"}
 else {
   warn "Module version: $Math::MPFR::VERSION\nXS version: ", Math::MPFR::_get_xs_version(), "\n";
   print "not ok 2\n";
@@ -48,3 +48,11 @@ else {
   warn "\n\$max_base: $max_base\n";
   print "not ok 4\n";
 }
+
+if(Math::MPFR::_has_longlong() && Math::MPFR::_ivsize_bits() == (8 * $Config{ivsize})) {print "ok 5\n"}
+elsif(!Math::MPFR::_has_longlong()) {print "ok 5\n"}
+else {
+  warn "\n _has_longlong(): ", Math::MPFR::_has_longlong(), "\n _ivsize_bits: ",
+        Math::MPFR::_ivsize_bits(), "\n";
+  print "not ok 5\n";
+}
@@ -2,12 +2,17 @@ use strict;
 use warnings;
 use Math::MPFR qw(:mpfr);
 
-print "1..10\n";
+print "1..11\n";
 
 eval{my $p = MPFR_DBL_DIG;};
 
 if(!$@) {
-  warn "\nFYI:\n DBL_DIG = ", MPFR_DBL_DIG, "\n";
+  if(defined(MPFR_DBL_DIG)) {
+    warn "\nFYI:\n DBL_DIG = ", MPFR_DBL_DIG, "\n";
+  }
+  else {
+    warn "\nFYI:\n DBL_DIG not defined\n";
+  }
   print "ok 1\n";
 }
 else {
@@ -18,7 +23,12 @@ else {
 eval{my $lp = MPFR_LDBL_DIG;};
 
 if(!$@) {
-  warn  "\nFYI:\n LDBL_DIG = ", MPFR_LDBL_DIG, "\n";
+  if(defined(MPFR_LDBL_DIG)) {
+    warn  "\nFYI:\n LDBL_DIG = ", MPFR_LDBL_DIG, "\n";
+  }
+  else {
+    warn "\nFYI:\n LDBL_DIG not defined\n";
+  }
   print "ok 2\n";
 }
 else {
@@ -26,50 +36,66 @@ else {
   print "not ok 2\n";
 }
 
-if(mpfr_max_orig_len(10, 2, 55) == 16){print "ok 3\n"}
+eval{my $f128p = MPFR_FLT128_DIG;};
+
+if(!$@) {
+  if(defined(MPFR_FLT128_DIG)) {
+    warn  "\nFYI:\n FLT128_DIG = ", MPFR_FLT128_DIG, "\n";
+  }
+  else {
+    warn "\nFYI:\n FLT128_DIG not defined\n";
+  }
+  print "ok 3\n";
+}
 else {
-  warn "\n3: Got ", mpfr_max_orig_len(10, 2, 55), "\nExpected 16\n";
+  warn "\$\@: $@";
   print "not ok 3\n";
 }
 
-if(mpfr_max_orig_len(2, 10, 17) == 53){print "ok 4\n"}
+if(mpfr_max_orig_len(10, 2, 55) == 16){print "ok 4\n"}
 else {
-  warn "\n4: Got ", mpfr_max_orig_len(2, 10, 17), "\nExpected 53\n";
+  warn "\n4: Got ", mpfr_max_orig_len(10, 2, 55), "\nExpected 16\n";
   print "not ok 4\n";
 }
 
-if(mpfr_min_inter_prec(2, 53, 10) == 17) {print "ok 5\n"}
+if(mpfr_max_orig_len(2, 10, 17) == 53){print "ok 5\n"}
 else {
-  warn "\n5: Got ", mpfr_min_inter_prec(2, 53, 10), "\nExpected 17\n";
+  warn "\n5: Got ", mpfr_max_orig_len(2, 10, 17), "\nExpected 53\n";
   print "not ok 5\n";
 }
 
-if(mpfr_min_inter_prec(10, 16, 2) == 55) {print "ok 6\n"}
+if(mpfr_min_inter_prec(2, 53, 10) == 17) {print "ok 6\n"}
 else {
-  warn "\n6: Got ", mpfr_min_inter_prec(10, 16, 2), "\nExpected 55\n";
+  warn "\n6: Got ", mpfr_min_inter_prec(2, 53, 10), "\nExpected 17\n";
   print "not ok 6\n";
 }
 
-if(mpfr_max_orig_base(53, 10, 17) == 2) {print "ok 7\n"}
+if(mpfr_min_inter_prec(10, 16, 2) == 55) {print "ok 7\n"}
 else {
-  warn "\n7: Got ", mpfr_max_orig_base(53, 10, 17), "\nExpected 2\n";
+  warn "\n7: Got ", mpfr_min_inter_prec(10, 16, 2), "\nExpected 55\n";
   print "not ok 7\n";
 }
 
-if(mpfr_max_orig_base(16, 2, 55) == 10) {print "ok 8\n"}
+if(mpfr_max_orig_base(53, 10, 17) == 2) {print "ok 8\n"}
 else {
-  warn "\n8: Got ", mpfr_max_orig_base(16, 2, 55), "\nExpected 10\n";
+  warn "\n8: Got ", mpfr_max_orig_base(53, 10, 17), "\nExpected 2\n";
   print "not ok 8\n";
 }
 
-if(mpfr_min_inter_base(10, 16, 55) ==2) {print "ok 9\n"}
+if(mpfr_max_orig_base(16, 2, 55) == 10) {print "ok 9\n"}
 else {
-  warn "\n9: Got ", mpfr_min_inter_base(10, 16, 55), "\nExpected 2\n";
+  warn "\n9: Got ", mpfr_max_orig_base(16, 2, 55), "\nExpected 10\n";
   print "not ok 9\n";
 }
 
-if(mpfr_min_inter_base(2, 53, 17) ==10) {print "ok 10\n"}
+if(mpfr_min_inter_base(10, 16, 55) ==2) {print "ok 10\n"}
 else {
-  warn "\n10: Got ", mpfr_min_inter_base(2, 53, 17), "\nExpected 10\n";
+  warn "\n10: Got ", mpfr_min_inter_base(10, 16, 55), "\nExpected 2\n";
   print "not ok 10\n";
 }
+
+if(mpfr_min_inter_base(2, 53, 17) ==10) {print "ok 11\n"}
+else {
+  warn "\n11: Got ", mpfr_min_inter_base(2, 53, 17), "\nExpected 10\n";
+  print "not ok 11\n";
+}
@@ -28,9 +28,9 @@ if($proceed) {
     my $larg_2 = $larg_1 ? 5 - $larg_1 : $larg_1;
     my $d64_1 = NVtoD64($nv);
     my $fr_1 = Math::MPFR->new();
-    Rmpfr_set_decimal64($fr_1, $d64_1, $larg_1);
+    Rmpfr_set_DECIMAL64($fr_1, $d64_1, $larg_1);
     my $d64_2 = NVtoD64(0);
-    Rmpfr_get_decimal64($d64_2, $fr_1, $larg_2);
+    Rmpfr_get_DECIMAL64($d64_2, $fr_1, $larg_2);
     unless($d64_1 == $d64_2) {
       $ok = 0;
       warn "$it: $d64_1 != $d64_2\n   $larg_1 : $larg_2\n\n";
@@ -46,9 +46,9 @@ if($proceed) {
     my $nv = rand(1024) / (1 + rand(1024));
     my $d64_1 = NVtoD64($nv);
     my $fr_1 = Math::MPFR->new();
-    Rmpfr_set_decimal64($fr_1, $d64_1, 0);
+    Rmpfr_set_DECIMAL64($fr_1, $d64_1, 0);
     my $d64_2 = NVtoD64(0);
-    Rmpfr_get_decimal64($d64_2, $fr_1, 0);
+    Rmpfr_get_DECIMAL64($d64_2, $fr_1, 0);
     unless($d64_1 == $d64_2) {
       $ok = 0;
       warn "$it: $d64_1 != $d64_2\n";
@@ -66,8 +66,8 @@ if($proceed) {
 
   my $fr = Math::MPFR->new();
 
-  Rmpfr_set_decimal64($fr, $nanD64, MPFR_RNDN);
-  Rmpfr_get_decimal64($rop, $fr, MPFR_RNDN);
+  Rmpfr_set_DECIMAL64($fr, $nanD64, MPFR_RNDN);
+  Rmpfr_get_DECIMAL64($rop, $fr, MPFR_RNDN);
 
   if(is_NaND64($rop)) {print "ok 3\n"}
   else {
@@ -75,8 +75,8 @@ if($proceed) {
     print "not ok 3\n";
   }
 
-  Rmpfr_set_decimal64($fr, $pinfD64, MPFR_RNDN);
-  Rmpfr_get_decimal64($rop, $fr, MPFR_RNDN);
+  Rmpfr_set_DECIMAL64($fr, $pinfD64, MPFR_RNDN);
+  Rmpfr_get_DECIMAL64($rop, $fr, MPFR_RNDN);
 
   if(is_InfD64($rop) > 0) {print "ok 4\n"}
   else {
@@ -84,8 +84,8 @@ if($proceed) {
     print "not ok 4\n";
   }
 
-  Rmpfr_set_decimal64($fr, $ninfD64, MPFR_RNDN);
-  Rmpfr_get_decimal64($rop, $fr, MPFR_RNDN);
+  Rmpfr_set_DECIMAL64($fr, $ninfD64, MPFR_RNDN);
+  Rmpfr_get_DECIMAL64($rop, $fr, MPFR_RNDN);
 
   if(is_InfD64($rop) < 0) {print "ok 5\n"}
   else {
@@ -93,8 +93,8 @@ if($proceed) {
     print "not ok 5\n";
   }
 
-  Rmpfr_set_decimal64($fr, $zeroD64, MPFR_RNDN);
-  Rmpfr_get_decimal64($rop, $fr, MPFR_RNDN);
+  Rmpfr_set_DECIMAL64($fr, $zeroD64, MPFR_RNDN);
+  Rmpfr_get_DECIMAL64($rop, $fr, MPFR_RNDN);
 
   if(is_ZeroD64($rop) > 0) {print "ok 6\n"}
   else {
@@ -102,8 +102,8 @@ if($proceed) {
     print "not ok 6\n";
   }
 
-  Rmpfr_set_decimal64($fr, $nzeroD64, MPFR_RNDN);
-  Rmpfr_get_decimal64($rop, $fr, MPFR_RNDN);
+  Rmpfr_set_DECIMAL64($fr, $nzeroD64, MPFR_RNDN);
+  Rmpfr_get_DECIMAL64($rop, $fr, MPFR_RNDN);
 
   if(is_ZeroD64($rop) < 0) {print "ok 7\n"}
   else {
@@ -114,21 +114,21 @@ if($proceed) {
   my $bigpos = Math::MPFR->new('1@385');
   my $bigneg = $bigpos * -1;
 
-  Rmpfr_get_decimal64($rop, $bigpos, MPFR_RNDN);
+  Rmpfr_get_DECIMAL64($rop, $bigpos, MPFR_RNDN);
   if(is_InfD64($rop) > 0) {print "ok 8\n"}
   else {
     warn "\n\$rop: $rop\n";
     print "not ok 8\n";
   }
 
-  Rmpfr_get_decimal64($rop, $bigneg, MPFR_RNDN);
+  Rmpfr_get_DECIMAL64($rop, $bigneg, MPFR_RNDN);
   if(is_InfD64($rop) < 0) {print "ok 9\n"}
   else {
     warn "\n\$rop: $rop\n";
     print "not ok 9\n";
   }
 
-  Rmpfr_get_decimal64($rop, $bigpos, MPFR_RNDZ);
+  Rmpfr_get_DECIMAL64($rop, $bigpos, MPFR_RNDZ);
   if($rop == Math::Decimal64->new('9999999999999999','369')) {print "ok 10\n"}
   else {
     warn "\n\$rop: $rop\n";
@@ -150,28 +150,28 @@ if($proceed) {
   my $littlepos = Math::MPFR->new('1@-399');
   my $littleneg = $littlepos * -1;
 
-  Rmpfr_get_decimal64($rop, $littlepos, MPFR_RNDZ);
+  Rmpfr_get_DECIMAL64($rop, $littlepos, MPFR_RNDZ);
   if(is_ZeroD64($rop) > 0) {print "ok 13\n"}
   else {
     warn "\n\$rop: $rop\n";
     print "not ok 13\n";
   }
 
-  Rmpfr_get_decimal64($rop, $littleneg, MPFR_RNDZ);
+  Rmpfr_get_DECIMAL64($rop, $littleneg, MPFR_RNDZ);
   if(is_ZeroD64($rop) < 0) {print "ok 14\n"}
   else {
     warn "\n\$rop: $rop\n";
     print "not ok 14\n";
   }
 
-  Rmpfr_get_decimal64($rop, $littlepos, MPFR_RNDA);
+  Rmpfr_get_DECIMAL64($rop, $littlepos, MPFR_RNDA);
   if($rop == Math::Decimal64->new(1, -398)) {print "ok 15\n"}
   else {
     warn "\n\$rop: $rop\n";
     print "not ok 15\n";
   }
 
-  Rmpfr_get_decimal64($rop, $littleneg, MPFR_RNDA);
+  Rmpfr_get_DECIMAL64($rop, $littleneg, MPFR_RNDA);
   if($rop == Math::Decimal64->new(-1, -398)) {print "ok 16\n"}
   else {
     warn "\n\$rop: $rop\n";
@@ -187,8 +187,8 @@ if($proceed) {
   my $fr_d64 = Rmpfr_init2(55);
   my $d64_1 = MEtoD64('1', -298);
   my $d64_2 = Math::Decimal64->new();
-  Rmpfr_set_decimal64($fr_d64, $d64_1, MPFR_RNDN);
-  Rmpfr_get_decimal64($d64_2, $fr_d64, MPFR_RNDN);
+  Rmpfr_set_DECIMAL64($fr_d64, $d64_1, MPFR_RNDN);
+  Rmpfr_get_DECIMAL64($d64_2, $fr_d64, MPFR_RNDN);
   if($d64_1 == $d64_2) {print "ok 18\n"}
   else {
     warn "\n $d64_1: $d64_1\n \$d64_2: $d64_2\n";
@@ -196,8 +196,8 @@ if($proceed) {
   }
 
   $d64_1 = NVtoD64(1e-298);
-  Rmpfr_set_decimal64($fr_d64, $d64_1, MPFR_RNDN);
-  Rmpfr_get_decimal64($d64_2, $fr_d64, MPFR_RNDN);
+  Rmpfr_set_DECIMAL64($fr_d64, $d64_1, MPFR_RNDN);
+  Rmpfr_get_DECIMAL64($d64_2, $fr_d64, MPFR_RNDN);
   if($d64_1 == $d64_2) {print "ok 19\n"}
   else {
     warn "\n $d64_1: $d64_1\n \$d64_2: $d64_2\n";
@@ -205,8 +205,8 @@ if($proceed) {
   }
 
   $d64_1 = MEtoD64('1', -360);
-  Rmpfr_set_decimal64($fr_d64, $d64_1, MPFR_RNDN);
-  Rmpfr_get_decimal64($d64_2, $fr_d64, MPFR_RNDN);
+  Rmpfr_set_DECIMAL64($fr_d64, $d64_1, MPFR_RNDN);
+  Rmpfr_get_DECIMAL64($d64_2, $fr_d64, MPFR_RNDN);
   if($d64_1 == $d64_2) {print "ok 20\n"}
   else {
     warn "\n $d64_1: $d64_1\n \$d64_2: $d64_2\n";
@@ -214,8 +214,8 @@ if($proceed) {
   }
 
   $d64_1 = NVtoD64(1e-360);
-  Rmpfr_set_decimal64($fr_d64, $d64_1, MPFR_RNDN);
-  Rmpfr_get_decimal64($d64_2, $fr_d64, MPFR_RNDN);
+  Rmpfr_set_DECIMAL64($fr_d64, $d64_1, MPFR_RNDN);
+  Rmpfr_get_DECIMAL64($d64_2, $fr_d64, MPFR_RNDN);
   if($d64_1 == $d64_2) {print "ok 21\n"}
   else {
     warn "\n $d64_1: $d64_1\n \$d64_2: $d64_2\n";
@@ -43,9 +43,9 @@ if($proceed) {
     my $larg_2 = $larg_1 ? 5 - $larg_1 : $larg_1;
     my $f128_1 = NVtoF128($nv);
     my $fr_1 = Math::MPFR->new();
-    Rmpfr_set_float128($fr_1, $f128_1, $larg_1);
+    Rmpfr_set_FLOAT128($fr_1, $f128_1, $larg_1);
     my $f128_2 = NVtoF128(0);
-    Rmpfr_get_float128($f128_2, $fr_1, $larg_2);
+    Rmpfr_get_FLOAT128($f128_2, $fr_1, $larg_2);
     unless($f128_1 == $f128_2) {
       $ok = 0;
       warn "$it: $f128_1 != $f128_2\n   $larg_1 : $larg_2\n\n";
@@ -61,9 +61,9 @@ if($proceed) {
     my $nv = rand(1024) / (1 + rand(1024));
     my $f128_1 = NVtoF128($nv);
     my $fr_1 = Math::MPFR->new();
-    Rmpfr_set_float128($fr_1, $f128_1, 0);
+    Rmpfr_set_FLOAT128($fr_1, $f128_1, 0);
     my $f128_2 = NVtoF128(0);
-    Rmpfr_get_float128($f128_2, $fr_1, 0);
+    Rmpfr_get_FLOAT128($f128_2, $fr_1, 0);
     unless($f128_1 == $f128_2) {
       $ok = 0;
       warn "$it: $f128_1 != $f128_2\n";
@@ -81,8 +81,8 @@ if($proceed) {
 
   my $fr = Math::MPFR->new();
 
-  Rmpfr_set_float128($fr, $nanF128, MPFR_RNDN);
-  Rmpfr_get_float128($rop, $fr, MPFR_RNDN);
+  Rmpfr_set_FLOAT128($fr, $nanF128, MPFR_RNDN);
+  Rmpfr_get_FLOAT128($rop, $fr, MPFR_RNDN);
 
   if(is_NaNF128($rop)) {print "ok 3\n"}
   else {
@@ -90,8 +90,8 @@ if($proceed) {
     print "not ok 3\n";
   }
 
-  Rmpfr_set_float128($fr, $pinfF128, MPFR_RNDN);
-  Rmpfr_get_float128($rop, $fr, MPFR_RNDN);
+  Rmpfr_set_FLOAT128($fr, $pinfF128, MPFR_RNDN);
+  Rmpfr_get_FLOAT128($rop, $fr, MPFR_RNDN);
 
   if(is_InfF128($rop) > 0) {print "ok 4\n"}
   else {
@@ -99,8 +99,8 @@ if($proceed) {
     print "not ok 4\n";
   }
 
-  Rmpfr_set_float128($fr, $ninfF128, MPFR_RNDN);
-  Rmpfr_get_float128($rop, $fr, MPFR_RNDN);
+  Rmpfr_set_FLOAT128($fr, $ninfF128, MPFR_RNDN);
+  Rmpfr_get_FLOAT128($rop, $fr, MPFR_RNDN);
 
   if(is_InfF128($rop) < 0) {print "ok 5\n"}
   else {
@@ -108,8 +108,8 @@ if($proceed) {
     print "not ok 5\n";
   }
 
-  Rmpfr_set_float128($fr, $zeroF128, MPFR_RNDN);
-  Rmpfr_get_float128($rop, $fr, MPFR_RNDN);
+  Rmpfr_set_FLOAT128($fr, $zeroF128, MPFR_RNDN);
+  Rmpfr_get_FLOAT128($rop, $fr, MPFR_RNDN);
 
   if(is_ZeroF128($rop) > 0) {print "ok 6\n"}
   else {
@@ -117,8 +117,8 @@ if($proceed) {
     print "not ok 6\n";
   }
 
-  Rmpfr_set_float128($fr, $nzeroF128, MPFR_RNDN);
-  Rmpfr_get_float128($rop, $fr, MPFR_RNDN);
+  Rmpfr_set_FLOAT128($fr, $nzeroF128, MPFR_RNDN);
+  Rmpfr_get_FLOAT128($rop, $fr, MPFR_RNDN);
 
   if(is_ZeroF128($rop) < 0) {print "ok 7\n"}
   else {
@@ -129,21 +129,21 @@ if($proceed) {
   my $bigpos = Math::MPFR->new('1.4e4932');
   my $bigneg = $bigpos * -1;
 
-  Rmpfr_get_float128($rop, $bigpos, MPFR_RNDN);
+  Rmpfr_get_FLOAT128($rop, $bigpos, MPFR_RNDN);
   if(is_InfF128($rop) > 0) {print "ok 8\n"}
   else {
     warn "\n\$rop: $rop\n";
     print "not ok 8\n";
   }
 
-  Rmpfr_get_float128($rop, $bigneg, MPFR_RNDN);
+  Rmpfr_get_FLOAT128($rop, $bigneg, MPFR_RNDN);
   if(is_InfF128($rop) < 0) {print "ok 9\n"}
   else {
     warn "\n\$rop: $rop\n";
     print "not ok 9\n";
   }
 
-  Rmpfr_get_float128($rop, Math::MPFR->new('1.18973149535723176508575932662800702e4932'), MPFR_RNDZ);
+  Rmpfr_get_FLOAT128($rop, Math::MPFR->new('1.18973149535723176508575932662800702e4932'), MPFR_RNDZ);
   if($rop == Math::Float128->new('1.18973149535723176508575932662800702e4932')) {print "ok 10\n"}
   else {
     warn "\n\$rop: $rop\n";
@@ -165,35 +165,35 @@ if($proceed) {
   my $littlepos = Math::MPFR->new('7e-4967');
   my $littleneg = $littlepos * -1;
 
-  Rmpfr_get_float128($rop, $littlepos, MPFR_RNDZ);
+  Rmpfr_get_FLOAT128($rop, $littlepos, MPFR_RNDZ);
   if(is_ZeroF128($rop) > 0) {print "ok 13\n"}
   else {
     warn "\n\$rop: $rop\n";
     print "not ok 13\n";
   }
 
-  Rmpfr_get_float128($rop, $littleneg, MPFR_RNDZ);
+  Rmpfr_get_FLOAT128($rop, $littleneg, MPFR_RNDZ);
   if(is_ZeroF128($rop) < 0) {print "ok 14\n"}
   else {
     warn "\n\$rop: $rop\n";
     print "not ok 14\n";
   }
 
-  Rmpfr_get_float128($rop, $littlepos, MPFR_RNDA);
+  Rmpfr_get_FLOAT128($rop, $littlepos, MPFR_RNDA);
   if(is_ZeroF128($rop) > 0) {print "ok 15\n"}
   else {
     warn "\n\$rop: $rop\n";
     print "not ok 15\n";
   }
 
-  Rmpfr_get_float128($rop, $littleneg, MPFR_RNDA);
+  Rmpfr_get_FLOAT128($rop, $littleneg, MPFR_RNDA);
   if(is_ZeroF128($rop) < 0) {print "ok 16\n"}
   else {
     warn "\n\$rop: $rop\n";
     print "not ok 16\n";
   }
 
-  Rmpfr_get_float128($rop, Math::MPFR->new('6.475175119438025110924438958227646552e-4966'), MPFR_RNDN);
+  Rmpfr_get_FLOAT128($rop, Math::MPFR->new('6.475175119438025110924438958227646552e-4966'), MPFR_RNDN);
   if($rop == Math::Float128::FLT128_DENORM_MIN()) {print "ok 17\n"}
   else {
     warn "\n\$rop: $rop\n";
@@ -203,8 +203,8 @@ if($proceed) {
   my $fr_F128 = Rmpfr_init2(115);
   my $f128_1 = STRtoF128('1e-298');
   my $f128_2 = Math::Float128->new();
-  Rmpfr_set_float128($fr_F128, $f128_1, MPFR_RNDN);
-  Rmpfr_get_float128($f128_2, $fr_F128, MPFR_RNDN);
+  Rmpfr_set_FLOAT128($fr_F128, $f128_1, MPFR_RNDN);
+  Rmpfr_get_FLOAT128($f128_2, $fr_F128, MPFR_RNDN);
   if($f128_1 == $f128_2) {print "ok 18\n"}
   else {
     warn "\n $f128_1: $f128_1\n \$f128_2: $f128_2\n";
@@ -212,8 +212,8 @@ if($proceed) {
   }
 
   $f128_1 = NVtoF128(1e-298);
-  Rmpfr_set_float128($fr_F128, $f128_1, MPFR_RNDN);
-  Rmpfr_get_float128($f128_2, $fr_F128, MPFR_RNDN);
+  Rmpfr_set_FLOAT128($fr_F128, $f128_1, MPFR_RNDN);
+  Rmpfr_get_FLOAT128($f128_2, $fr_F128, MPFR_RNDN);
   if($f128_1 == $f128_2) {print "ok 19\n"}
   else {
     warn "\n $f128_1: $f128_1\n \$f128_2: $f128_2\n";
@@ -221,8 +221,8 @@ if($proceed) {
   }
 
   $f128_1 = STRtoF128('1e-360');
-  Rmpfr_set_float128($fr_F128, $f128_1, MPFR_RNDN);
-  Rmpfr_get_float128($f128_2, $fr_F128, MPFR_RNDN);
+  Rmpfr_set_FLOAT128($fr_F128, $f128_1, MPFR_RNDN);
+  Rmpfr_get_FLOAT128($f128_2, $fr_F128, MPFR_RNDN);
   if($f128_1 == $f128_2) {print "ok 20\n"}
   else {
     warn "\n $f128_1: $f128_1\n \$f128_2: $f128_2\n";
@@ -230,8 +230,8 @@ if($proceed) {
   }
 
   $f128_1 = NVtoF128(1e-360);
-  Rmpfr_set_float128($fr_F128, $f128_1, MPFR_RNDN);
-  Rmpfr_get_float128($f128_2, $fr_F128, MPFR_RNDN);
+  Rmpfr_set_FLOAT128($fr_F128, $f128_1, MPFR_RNDN);
+  Rmpfr_get_FLOAT128($f128_2, $fr_F128, MPFR_RNDN);
   if($f128_1 == $f128_2) {print "ok 21\n"}
   else {
     warn "\n $f128_1: $f128_1\n \$f128_2: $f128_2\n";
@@ -0,0 +1,65 @@
+use strict;
+use warnings;
+use Config;
+use Math::MPFR qw(:mpfr);
+
+my $t = 1;
+
+if(Math::MPFR::_can_pass_float128()) {
+  print "1..$t\n";
+  warn "\n Can pass _float128 between perl subs and XSubs\n";
+
+  Rmpfr_set_default_prec(113);
+
+  my $frac = 3.0; # For me, both C and perl miscalculates sqrt(2.0), so we'll
+                  # sweep that one under the carpet and check using sqrt(3.0),
+                  # which seems to be calculated correctly.
+
+  my $fr = Math::MPFR->new($frac);
+  $fr **= 0.5;
+  if($fr == sqrt($frac)) {print "ok 1\n"}
+  else {
+    my $check = sprintf "%a", Rmpfr_get_float128($fr, MPFR_RNDN);
+    warn "\n Expected $check\n      Got ", sprintf "%a\n", sqrt($frac);
+    print "not ok 1\n";
+  }
+}
+elsif($Config{nvtype} eq '__float128') {
+  print "1..$t\n";
+
+  # First, work out the precision of the long double:
+  my ($frac, $prec) = (2.0, 0);
+  my $hex = scalar reverse unpack "h*", pack "D<", sqrt($frac);
+
+  $hex =~ s/^0+//;
+  my $len = length $hex;
+
+  $prec = $len == 20 ? 64
+                     : $len == 32 ? 113 : 0;
+
+  if(!$prec) {
+    warn "\n Skipping tests - couldn't determine precision of long double\n";
+    print "ok $_\n" for 1 .. $t;
+    exit 0;
+  }
+
+  warn "\n Casting __float128 to $prec-bit precision long double\n";
+
+  Rmpfr_set_default_prec($prec);
+
+  my $fr1 = Math::MPFR->new(sqrt($frac));
+  my $fr2 = Math::MPFR->new();
+  Rmpfr_set_ld($fr2, sqrt($frac), MPFR_RNDN);
+
+  if($fr1 == $fr2) {print "ok 1\n"}
+  else {
+    warn "\n$fr1 != $fr2\n";
+    print "not ok 1\n";
+  }
+}
+else {
+  print "1..1\n";
+  warn "\n Skipping all tests - nvtype is $Config{nvtype}\n";
+  print "ok 1\n";
+  exit 0;
+}
@@ -120,7 +120,7 @@ Rmpfr_set_default_prec(100);
 my $f27 = Math::MPFR->new(36028797018964023);
 my $f28 = Math::MPFR->new('36028797018964023');
 
-if(Math::MPFR::_has_longlong()) {
+if(Math::MPFR::_has_longlong() || $Config{ivsize} >= 8) {
   if($f27 == $f28) {$ok .= 'i'}
   else {warn "== : $f27 $f28\n"}
 }
@@ -93,7 +93,8 @@ else {
   $ok = 'abcdefgh';
 }
 
-my $bits = Math::MPFR::_has_longlong() ? 32 : 16;
+#my $bits = Math::MPFR::_has_longlong() ? 32 : 16;
+my $bits = $Config{ivsize} > 4 ? 32 : 16;
 
 if($mpfr1 ** 0.5 < 2 ** $bits &&
    $mpfr1 ** 0.5 > (2 ** $bits) - 1 ) {$ok .= 'i'}
@@ -144,6 +145,9 @@ elsif(Math::MPFR::_has_longlong()){
   }
   else {Rmpfr_set_str($mpfr1, (~0 - 1) / -2, 10, GMP_RNDN)}
 }
+elsif($Config{ivsize} >= 8) { # Not a 'long long'; must be a 'long'
+  Rmpfr_set_si($mpfr1, (~0 - 1) / -2, GMP_RNDN);
+}
 else {
   Rmpfr_set_d($mpfr1, (~0 - 1) / -2, GMP_RNDN);
 }
@@ -367,9 +367,13 @@ else {print "not ok 22\n"}
 $z = $c;
 $z *= -1;
 if($z == -$c
-   && Math::MPFR::get_refcnt($z) == 1
-   && Math::MPFR::get_refcnt($c) == 1) {print "ok 23\n"}
-else {print "not ok 23\n"}
+  && Math::MPFR::get_refcnt($z) == 1
+  && Math::MPFR::get_refcnt($c) == 1) {print "ok 23\n"}
+else {
+  warn "\$z: $z -\$c: ", -$c, "\n";
+  warn "refcounts are ", Math::MPFR::get_refcnt($z), " and ", Math::MPFR::get_refcnt($c), "\n";
+  print "not ok 23\n";
+}
 
 $ok = '';
 
@@ -12,9 +12,12 @@ my ($ret1, $ret2);
 
 $ret1 = Rmpfr_set_NV($fr1, sqrt(2.0), MPFR_RNDN);
 
-if(Math::MPFR::_has_longdouble()) {
+if(Math::MPFR::_has_longdouble() && !Math::MPFR::_can_pass_float128()) {
   $ret2 = Rmpfr_set_ld($fr2, sqrt(2.0), MPFR_RNDN);
 }
+elsif(Math::MPFR::_can_pass_float128()) {
+  $ret2 = Rmpfr_set_float128($fr2, sqrt(2.0), MPFR_RNDN);
+}
 else {
   $ret2 = Rmpfr_set_d($fr2, sqrt(2.0), MPFR_RNDN);
 }