    package Math::MPC;
    use strict;
    use warnings;
    use Math::MPFR;
    use Math::MPC::Constant;

    use constant  MPC_RNDNN => 0;
    use constant  MPC_RNDZN => 1;
    use constant  MPC_RNDUN => 2;
    use constant  MPC_RNDDN => 3;
    use constant  MPC_RNDAN => 4;

    use constant  MPC_RNDNZ => 16;
    use constant  MPC_RNDZZ => 17;
    use constant  MPC_RNDUZ => 18;
    use constant  MPC_RNDDZ => 19;
    use constant  MPC_RNDAZ => 20;

    use constant  MPC_RNDNU => 32;
    use constant  MPC_RNDZU => 33;
    use constant  MPC_RNDUU => 34;
    use constant  MPC_RNDDU => 35;
    use constant  MPC_RNDAU => 36;

    use constant  MPC_RNDND => 48;
    use constant  MPC_RNDZD => 49;
    use constant  MPC_RNDUD => 50;
    use constant  MPC_RNDDD => 51;
    use constant  MPC_RNDAD => 52;

    use constant  MPC_RNDNA => 64;
    use constant  MPC_RNDZA => 65;
    use constant  MPC_RNDUA => 66;
    use constant  MPC_RNDDA => 67;
    use constant  MPC_RNDAA => 68;

    use constant  _UOK_T   => 1;
    use constant  _IOK_T   => 2;
    use constant  _NOK_T   => 3;
    use constant  _POK_T   => 4;
    use constant  _MATH_MPFR_T   => 5;
    use constant  _MATH_GMPf_T   => 6;
    use constant  _MATH_GMPq_T   => 7;
    use constant  _MATH_GMPz_T   => 8;
    use constant  _MATH_GMP_T    => 9;
    use constant  _MATH_MPC_T    => 10;

    use constant MPC_PV_NV_BUG => Math::MPC::Constant::_has_pv_nv_bug();
    use constant MPC_HEADER_V  => Math::MPC::Constant::_mpc_header_version();
    use constant MPC_HEADER_V_STR => Math::MPC::Constant::_mpc_header_version_str();

    # In reaction to https://github.com/Perl/perl5/issues/19550, which affects only perl-5.35.10:
    use constant ISSUE_19550    => Math::MPC::Constant::_issue_19550();

    use subs qw(MPC_VERSION MPC_VERSION_MAJOR MPC_VERSION_MINOR
                MPC_VERSION_PATCHLEVEL MPC_VERSION_STRING
                MPC_VERSION_NUM);

    use overload
    '+'    => \&overload_add,
    '-'    => \&overload_sub,
    '*'    => \&overload_mul,
    '/'    => \&overload_div,
    '**'   => \&overload_pow,
    '+='   => \&overload_add_eq,
    '-='   => \&overload_sub_eq,
    '*='   => \&overload_mul_eq,
    '/='   => \&overload_div_eq,
    '**='  => \&overload_pow_eq,
    '=='   => \&overload_equiv,
    '!='   => \&overload_not_equiv,
    '!'    => \&overload_not,
    '='    => \&overload_copy,
    '""'   => \&overload_string,
    'abs'  => \&overload_abs,
    'bool' => \&overload_true,
    'exp'  => \&overload_exp,
    'log'  => \&overload_log,
    'sqrt' => \&overload_sqrt,
    'sin'  => \&overload_sin,
    'cos'  => \&overload_cos,
    'atan2'=> \&overload_atan2;

    require Exporter;
    *import = \&Exporter::import;
    require DynaLoader;

    my @tagged = qw(
MPC_PV_NV_BUG MPC_HEADER_V MPC_HEADER_V_STR
MPC_RNDNN MPC_RNDND MPC_RNDNU MPC_RNDNZ MPC_RNDDN MPC_RNDUN MPC_RNDZN MPC_RNDDD
MPC_RNDDU MPC_RNDDZ MPC_RNDZD MPC_RNDUD MPC_RNDUU MPC_RNDUZ MPC_RNDZU MPC_RNDZZ
MPC_RNDNA MPC_RNDAN MPC_RNDAZ MPC_RNDZA MPC_RNDAD MPC_RNDDA MPC_RNDUA MPC_RNDAU
MPC_RNDAA
MPC_VERSION_MAJOR MPC_VERSION_MINOR MPC_VERSION_PATCHLEVEL MPC_VERSION_STRING
MPC_VERSION MPC_VERSION_NUM Rmpc_get_version
Rmpc_set_default_rounding_mode Rmpc_get_default_rounding_mode
Rmpc_set_prec Rmpc_set_default_prec Rmpc_get_default_prec
Rmpc_set_default_prec2 Rmpc_get_default_prec2
Rmpc_set_re_prec Rmpc_set_im_prec
Rmpc_get_prec Rmpc_get_prec2 Rmpc_get_re_prec Rmpc_get_im_prec
Rmpc_get_dc Rmpc_get_ldc
Rmpc_get_DC Rmpc_get_LDC Rmpc_get_F128C
RMPC_RE RMPC_IM RMPC_INEX_RE RMPC_INEX_IM
Rmpc_clear Rmpc_clear_ptr Rmpc_clear_mpc
Rmpc_deref4 Rmpc_get_str
Rmpc_init2 Rmpc_init3
Rmpc_init2_nobless Rmpc_init3_nobless
Rmpc_strtoc Rmpc_set_str
Rmpc_set Rmpc_set_ui Rmpc_set_si Rmpc_set_d Rmpc_set_uj Rmpc_set_sj Rmpc_set_ld
Rmpc_set_z Rmpc_set_q Rmpc_set_f Rmpc_set_fr
Rmpc_set_z_z Rmpc_set_q_q Rmpc_set_f_f
Rmpc_set_ui_ui Rmpc_set_ui_si Rmpc_set_ui_d Rmpc_set_ui_uj Rmpc_set_ui_sj Rmpc_set_ui_ld Rmpc_set_ui_fr
Rmpc_set_si_ui Rmpc_set_si_si Rmpc_set_si_d Rmpc_set_si_uj Rmpc_set_si_sj Rmpc_set_si_ld Rmpc_set_si_fr
Rmpc_set_d_ui Rmpc_set_d_si Rmpc_set_d_d Rmpc_set_d_uj Rmpc_set_d_sj Rmpc_set_d_ld Rmpc_set_d_fr
Rmpc_set_uj_ui Rmpc_set_uj_si Rmpc_set_uj_d Rmpc_set_uj_uj Rmpc_set_uj_sj Rmpc_set_uj_ld Rmpc_set_uj_ld Rmpc_set_uj_fr
Rmpc_set_sj_ui Rmpc_set_sj_si Rmpc_set_sj_d Rmpc_set_sj_uj Rmpc_set_sj_sj Rmpc_set_sj_ld Rmpc_set_sj_fr
Rmpc_set_ld_ui Rmpc_set_ld_si Rmpc_set_ld_uj Rmpc_set_ld_d Rmpc_set_ld_sj Rmpc_set_ld_ld Rmpc_set_ld_fr
Rmpc_set_fr_ui Rmpc_set_fr_si Rmpc_set_fr_d Rmpc_set_fr_uj Rmpc_set_fr_sj Rmpc_set_fr_ld Rmpc_set_fr_fr

Rmpc_set_f_ui Rmpc_set_q_ui Rmpc_set_z_ui Rmpc_set_ui_f Rmpc_set_ui_q Rmpc_set_ui_z
Rmpc_set_f_si Rmpc_set_q_si Rmpc_set_z_si Rmpc_set_si_f Rmpc_set_si_q Rmpc_set_si_z
Rmpc_set_f_d Rmpc_set_q_d Rmpc_set_z_d Rmpc_set_d_f Rmpc_set_d_q Rmpc_set_d_z
Rmpc_set_f_uj Rmpc_set_q_uj Rmpc_set_z_uj Rmpc_set_uj_f Rmpc_set_uj_q Rmpc_set_uj_z
Rmpc_set_f_sj Rmpc_set_q_sj Rmpc_set_z_sj Rmpc_set_sj_f Rmpc_set_sj_q Rmpc_set_sj_z
Rmpc_set_f_ld Rmpc_set_q_ld Rmpc_set_z_ld Rmpc_set_ld_f Rmpc_set_ld_q Rmpc_set_ld_z
Rmpc_set_f_q Rmpc_set_q_f Rmpc_set_f_z Rmpc_set_z_f Rmpc_set_z_q Rmpc_set_q_z
Rmpc_set_f_fr Rmpc_set_q_fr Rmpc_set_z_fr Rmpc_set_fr_f Rmpc_set_fr_q Rmpc_set_fr_z

Rmpc_set_dc Rmpc_set_ldc Rmpc_set_NV Rmpc_set_NV_NV
Rmpc_set_DC Rmpc_set_LDC Rmpc_set_F128C
Rmpc_fma Rmpc_dot Rmpc_sum
Rmpc_add Rmpc_add_ui Rmpc_add_fr
Rmpc_sub Rmpc_sub_ui Rmpc_ui_sub Rmpc_ui_ui_sub Rmpc_sub_fr Rmpc_fr_sub
Rmpc_mul Rmpc_mul_ui Rmpc_mul_si Rmpc_mul_fr Rmpc_mul_i Rmpc_sqr Rmpc_mul_2exp
Rmpc_mul_2si Rmpc_mul_2ui
Rmpc_div Rmpc_div_ui Rmpc_ui_div Rmpc_div_fr Rmpc_fr_div Rmpc_sqrt Rmpc_div_2exp
Rmpc_div_2si Rmpc_div_2ui
Rmpc_neg Rmpc_abs Rmpc_conj Rmpc_norm
Rmpc_exp Rmpc_exp10 Rmpc_exp2 Rmpc_log Rmpc_log10 Rmpc_log2
Rmpc_cmp Rmpc_cmp_si Rmpc_cmp_si_si Rmpc_cmp_abs
Rmpc_out_str Rmpc_inp_str c_string r_string i_string
TRmpc_out_str TRmpc_inp_str
Rmpc_sin Rmpc_cos Rmpc_sin_cos Rmpc_tan Rmpc_sinh Rmpc_cosh Rmpc_tanh
Rmpc_asin Rmpc_acos Rmpc_atan Rmpc_asinh Rmpc_acosh Rmpc_atanh
Rmpc_real Rmpc_imag Rmpc_arg Rmpc_proj
Rmpc_pow Rmpc_pow_d Rmpc_pow_ld Rmpc_pow_si Rmpc_pow_ui Rmpc_pow_z Rmpc_pow_fr Rmpc_rootofunity
Rmpc_set_nan Rmpc_swap
Rmpc_mul_sj Rmpc_mul_ld Rmpc_mul_d Rmpc_div_sj Rmpc_sj_div Rmpc_div_ld Rmpc_ld_div Rmpc_div_d Rmpc_d_div
Rmpc_agm Rmpc_eta_fund in_fund_dom
Rmpcb_split Rmpcr_split_mpfr
);

my @radius = ();
my @ball = ();
if(MPC_HEADER_V >= 66304) {
@radius = qw(
  Rmpcr_init  Rmpcr_init_nobless  Rmpcr_clear
  Rmpcr_inf_p  Rmpcr_zero_p  Rmpcr_lt_half_p  Rmpcr_cmp  Rmpcr_set_inf
  Rmpcr_set_zero  Rmpcr_set_one  Rmpcr_set  Rmpcr_set_ui64_2si64  Rmpcr_set_str_2str
  Rmpcr_max Rmpcr_add  Rmpcr_sub  Rmpcr_mul  Rmpcr_div
  Rmpcr_get_exp Rmpcr_get_exp_mpfr
  Rmpcr_mul_2ui  Rmpcr_div_2ui  Rmpcr_sqr  Rmpcr_sqrt  Rmpcr_sub_rnd
  Rmpcr_c_abs_rnd  Rmpcr_add_rounding_error
  Rmpcr_split
  Rmpcr_print      Rmpcr_say      Rmpcr_out_str
  Rmpcr_print_win  Rmpcr_say_win  Rmpcr_out_str_win
          );

@ball = qw (
  Rmpcb_init Rmpcb_init_nobless Rmpcb_clear
  Rmpcb_get_prec Rmpcb_set Rmpcb_set_c Rmpcb_set_ui_ui Rmpcb_neg
  Rmpcb_add Rmpcb_mul Rmpcb_sqr Rmpcb_pow_ui Rmpcb_sqrt
  Rmpcb_div Rmpcb_div_2ui Rmpcb_set_inf
  Rmpcb_can_round Rmpcb_round Rmpcb_retrieve Rmpcb_out_str
         );
}

    @Math::MPC::EXPORT_OK = (@tagged, @radius, @ball);
    our $VERSION = '1.43';
    #$VERSION = eval $VERSION;

    Math::MPC->DynaLoader::bootstrap($VERSION);

    %Math::MPC::EXPORT_TAGS =(mpc => [@tagged, @radius, @ball]);

$Math::MPC::NOK_POK = 0; # Set to 1 to allow warnings in new() and overloaded operations when
                          # a scalar that has set both NOK (NV) and POK (PV) flags is encountered

# The following 3 variables store the initial default precisions and default rounding mode.
# They can be altered by directly assigning new values to them, or by calling
# Rmpc_set_default_prec(), Rmpc_set_default_prec2() or Rmpc_set_default_rounding
# mode - which will assign the new values for you..
# The values can also be retrieved directly, or by calling Rmpc_get_default_prec(),
# Rmpc_get_default_prec2() or Rmpc_get_default_rounding_mode
$Math::MPC::DEFAULT_PREC_RE = 53;
$Math::MPC::DEFAULT_PREC_IM = 53;
$Math::MPC::DEFAULT_ROUNDING_MODE = MPC_RNDNN;

eval {require Math::Complex_C::Q;};

if($@) {$Math::MPC::no_complex_c_q = $@}
else   {$Math::MPC::no_complex_c_q = 0 }

*TRmpc_out_str = \&Rmpc_out_str;
*TRmpc_inp_str = \&Rmpc_inp_str;

*Rmpc_set_uj_si = \&Rmpc_set_uj_sj;
*Rmpc_set_ui_sj = \&Rmpc_set_uj_sj;

*Rmpc_set_sj_ui = \&Rmpc_set_sj_uj;
*Rmpc_set_si_uj = \&Rmpc_set_sj_uj;

*Rmpc_set_uj_ui = \&Rmpc_set_uj_uj;
*Rmpc_set_ui_uj = \&Rmpc_set_uj_uj;

*Rmpc_set_sj_si = \&Rmpc_set_sj_sj;
*Rmpc_set_si_sj = \&Rmpc_set_sj_sj;

*Rmpc_set_d_ld  = \&Rmpc_set_ld_ld;
*Rmpc_set_ld_d  = \&Rmpc_set_ld_ld;

# Beginning with mpc-1.0, mpc_mul_2exp and mpc_div_2exp
# were renamed to mpc_mul_2ui and mpc_div_2ui.
*Rmpc_mul_2exp = \&Rmpc_mul_2ui;
*Rmpc_div_2exp = \&Rmpc_div_2ui;

if(MPC_HEADER_V >= 66304) { # mpc library is at least version 1.3.0

  require Math::MPC::Radius;
  require Math::MPC::Ball;

  *Rmpcr_init = \&Math::MPC::Radius::Rmpcr_init;
  *Rmpcr_init_nobless = \&Math::MPC::Radius::Rmpcr_init_nobless;
  *Rmpcr_clear = \&Math::MPC::Radius::Rmpcr_clear;
  *Rmpcr_inf_p = \&Math::MPC::Radius::Rmpcr_inf_p;
  *Rmpcr_zero_p = \&Math::MPC::Radius::Rmpcr_zero_p;
  *Rmpcr_lt_half_p = \&Math::MPC::Radius::Rmpcr_lt_half_p;
  *Rmpcr_cmp = \&Math::MPC::Radius::Rmpcr_cmp;
  *Rmpcr_set_inf = \&Math::MPC::Radius::Rmpcr_set_inf;
  *Rmpcr_set_zero = \&Math::MPC::Radius::Rmpcr_set_zero;
  *Rmpcr_set_one = \&Math::MPC::Radius::Rmpcr_set_one;
  *Rmpcr_set = \&Math::MPC::Radius::Rmpcr_set;
  *Rmpcr_set_ui64_2si64 = \&Math::MPC::Radius::Rmpcr_set_ui64_2si64;
  *Rmpcr_set_str_2str = \&Math::MPC::Radius::Rmpcr_set_str_2str;
  *Rmpcr_max = \&Math::MPC::Radius::Rmpcr_max;
  *Rmpcr_get_exp = \&Math::MPC::Radius::Rmpcr_get_exp;
  *Rmpcr_get_exp_mpfr = \&Math::MPC::Radius::Rmpcr_get_exp_mpfr;
  *Rmpcr_split = \&Math::MPC::Radius::Rmpcr_split;
  *Rmpcr_out_str     = \&Math::MPC::Radius::Rmpcr_out_str;
  *Rmpcr_out_str_win = \&Math::MPC::Radius::Rmpcr_out_str_win; # For MS Windows only
  *Rmpcr_print       = \&Math::MPC::Radius::Rmpcr_print;
  *Rmpcr_print_win   = \&Math::MPC::Radius::Rmpcr_print_win;   # For MS Windows only
  *Rmpcr_say         = \&Math::MPC::Radius::Rmpcr_say;
  *Rmpcr_say_win     = \&Math::MPC::Radius::Rmpcr_say_win;     # For MS Windows only
  *Rmpcr_add = \&Math::MPC::Radius::Rmpcr_add;
  *Rmpcr_sub = \&Math::MPC::Radius::Rmpcr_sub;
  *Rmpcr_mul = \&Math::MPC::Radius::Rmpcr_mul;
  *Rmpcr_div = \&Math::MPC::Radius::Rmpcr_div;
  *Rmpcr_mul_2ui = \&Math::MPC::Radius::Rmpcr_mul_2ui;
  *Rmpcr_div_2ui = \&Math::MPC::Radius::Rmpcr_div_2ui;
  *Rmpcr_sqr = \&Math::MPC::Radius::Rmpcr_sqr;
  *Rmpcr_sqrt = \&Math::MPC::Radius::Rmpcr_sqrt;
  *Rmpcr_sub_rnd = \&Math::MPC::Radius::Rmpcr_sub_rnd;
  *Rmpcr_c_abs_rnd = \&Math::MPC::Radius::Rmpcr_c_abs_rnd;
  *Rmpcr_add_rounding_error = \&Math::MPC::Radius::Rmpcr_add_rounding_error;

  *Rmpcb_init = \&Math::MPC::Ball::Rmpcb_init;
  *Rmpcb_init_nobless = \&Math::MPC::Ball::Rmpcb_init_nobless;
  *Rmpcb_clear = \&Math::MPC::Ball::Rmpcb_clear;
  *Rmpcb_get_prec = \&Math::MPC::Ball::Rmpcb_get_prec;
  *Rmpcb_set = \&Math::MPC::Ball::Rmpcb_set;
  *Rmpcb_set_inf = \&Math::MPC::Ball::Rmpcb_set_inf;
  *Rmpcb_set_c = \&Math::MPC::Ball::Rmpcb_set_c;
  *Rmpcb_set_ui_ui = \&Math::MPC::Ball::Rmpcb_set_ui_ui;
  *Rmpcb_neg = \&Math::MPC::Ball::Rmpcb_neg;
  *Rmpcb_add = \&Math::MPC::Ball::Rmpcb_add;
  *Rmpcb_mul = \&Math::MPC::Ball::Rmpcb_mul;
  *Rmpcb_sqr = \&Math::MPC::Ball::Rmpcb_sqr;
  *Rmpcb_pow_ui = \&Math::MPC::Ball::Rmpcb_pow_ui;
  *Rmpcb_sqrt = \&Math::MPC::Ball::Rmpcb_sqrt;
  *Rmpcb_div = \&Math::MPC::Ball::Rmpcb_div;
  *Rmpcb_div_2ui = \&Math::MPC::Ball::Rmpcb_div_2ui;
  *Rmpcb_can_round = \&Math::MPC::Ball::Rmpcb_can_round;
  *Rmpcb_round = \&Math::MPC::Ball::Rmpcb_round;
  *Rmpcb_retrieve = \&Math::MPC::Ball::Rmpcb_retrieve;
  *Rmpcb_out_str = \&Math::MPC::Ball::Rmpcb_out_str;
}

sub dl_load_flags {0} # Prevent DynaLoader from complaining and croaking

sub overload_not_equiv {
    return 0 if overload_equiv($_[0], $_[1], $_[2]);
    return 1;
}

sub overload_string {
  my $t = Math::MPFR::Rmpfr_init();

  RMPC_RE($t, $_[0]);
  my $ret = "($t ";
  RMPC_IM($t, $_[0]);
  return $ret . "$t)";
}

sub c_string {
    my $r_s = r_string($_[0], $_[1], $_[2], $_[3]);
    my $i_s = i_string($_[0], $_[1], $_[2], $_[3]);
    return ($r_s, $i_s);
}

sub r_string {
    my($mantissa, $exponent) = _get_r_string($_[0], $_[1], $_[2], $_[3]);
    if($mantissa =~ /\@nan\@/i || $mantissa =~ /\@inf\@/i) {return $mantissa}
    if($mantissa =~ /\-/ && $mantissa !~ /[^0,\-]/) {return '-0'}
    if($mantissa !~ /[^0,\-]/ ) {return '0'}
    my $sep = $_[1] <= 10 ? 'e' : '@';

    my $len = substr($mantissa, 0, 1) eq '-' ? 2 : 1;

    if(!$_[2]) {
      while(length($mantissa) > $len && substr($mantissa, -1, 1) eq '0') {
           substr($mantissa, -1, 1, '');
      }
    }

    $exponent--;

    if(length($mantissa) == $len) {
      if($exponent) {return $mantissa . $sep . $exponent}
      return $mantissa;
    }

    substr($mantissa, $len, 0, '.');
    if($exponent) {return $mantissa . $sep . $exponent}
    return $mantissa;
}

sub i_string {
    my($mantissa, $exponent) = _get_i_string($_[0], $_[1], $_[2], $_[3]);
    if($mantissa =~ /\@nan\@/i || $mantissa =~ /\@inf\@/i) {return $mantissa}
    if($mantissa =~ /\-/ && $mantissa !~ /[^0,\-]/) {return '-0'}
    if($mantissa !~ /[^0,\-]/ ) {return '0'}

    my $sep = $_[1] <= 10 ? 'e' : '@';

    my $len = substr($mantissa, 0, 1) eq '-' ? 2 : 1;

    if(!$_[2]) {
      while(length($mantissa) > $len && substr($mantissa, -1, 1) eq '0') {
           substr($mantissa, -1, 1, '');
      }
    }

    $exponent--;

    if(length($mantissa) == $len) {
      if($exponent) {return $mantissa . $sep . $exponent}
      return $mantissa;
    }

    substr($mantissa, $len, 0, '.');
    if($exponent) {return $mantissa . $sep . $exponent}
    return $mantissa;
}

sub Rmpc_deref4 {
    my ($r_m, $r_e) = _get_r_string($_[0], $_[1], $_[2], $_[3]);
    my ($i_m, $i_e) = _get_i_string($_[0], $_[1], $_[2], $_[3]);
    return ($r_m, $r_e, $i_m, $i_e);
}

sub Rmpc_set_F128C {
  if($Math::MPC::no_complex_c_q) {die "In Rmpc_set_F128C(): $Math::MPC::no_complex_c_q"}
  my $t_re = Math::MPFR::Rmpfr_init2(113);
  my $t_im = Math::MPFR::Rmpfr_init2(113);
  Math::MPFR::Rmpfr_set_float128($t_re, Math::Complex_C::Q::real_cq($_[1]), 0); # Round to nearest
  Math::MPFR::Rmpfr_set_float128($t_im, Math::Complex_C::Q::imag_cq($_[1]), 0);   # Round to nearest
  return Rmpc_set_fr_fr($_[0], $t_re, $t_im, $_[2]); # Now use specified rounding mode
}

sub Rmpc_get_F128C {
  if($Math::MPC::no_complex_c_q) {die "In Rmpc_set_F128C(): $Math::MPC::no_complex_c_q"}
  my $t = Math::MPFR::Rmpfr_init2(113);
  RMPC_RE($t, $_[1]);
  Math::Complex_C::Q::set_real_cq($_[0], Math::MPFR::Rmpfr_get_float128($t, $_[2] & 3));
  RMPC_IM($t, $_[1]);
  Math::Complex_C::Q::set_imag_cq($_[0], Math::MPFR::Rmpfr_get_float128($t, $_[2] / 16));
}


sub new {

    # This function caters for 2 possibilities:
    # 1) that 'new' has been called OOP style - in which
    #    case there will be a maximum of 3 args
    # 2) that 'new' has been called as a function - in
    #    which case there will be a maximum of 2 args.
    # If there are no args, then we just want to return an
    # initialized Math::MPC object
    my @prec = Rmpc_get_default_prec2();
    if(!@_) {return Rmpc_init3(@prec)}

    if(@_ > 3) {die "Too many arguments supplied to new()"}

    # If 'new' has been called OOP style, the first arg is the string "Math::MPC"
    # which we don't need - so let's remove it. However, if the first
    # arg is a Math::MPFR or Math::MPC object (which is a possibility),
    # then we'll get a fatal error when we check it for equivalence to
    # the string "Math::MPC". So we first need to check that it's not
    # an object - which we'll do by using the ref() function:
    if(!ref($_[0]) && $_[0] eq "Math::MPC") {
      shift;
      if(!@_) {return Rmpc_init3(@prec)}
      }

    if(_itsa($_[0]) == _MATH_MPC_T) {
      if(@_ > 1) {die "Too many arguments supplied to new() - expected no more than one"}
      my $mpc = Rmpc_init3(@prec);
      Rmpc_set($mpc, $_[0], Rmpc_get_default_rounding_mode());
      return $mpc;
    }

    # @_ can now contain a maximum of 2 args - the real and (optionally)
    # the imaginary components.
    if(@_ > 2) {die "Too many arguments supplied to new() - expected no more than two"}

    my ($arg1, $arg2, $type1, $type2);

    # $_[0] is the real component, $_[1] (if supplied)
    # is the imaginary component.
    $arg1 = shift;
    $type1 = _itsa($arg1);

    $arg2 = 0;
    if(@_) {$arg2 = shift}
    $type2 = _itsa($arg2);

    # Die if either of the args are unacceptable.
    if($type1 == 0)
      {die "First argument to new() is inappropriate"}
    if($type2 == 0)
      {die "Second argument to new() is inappropriate"}

    # Return a Math::MPC object that has $arg1 as its
    # real component, and $arg2 as its imaginary component.
    return _new_real_im($arg1, $arg2);
}

sub Rmpc_out_str {
    if(@_ == 5) {
      die "Inappropriate 4th arg supplied to Rmpc_out_str" if _itsa($_[3]) != _MATH_MPC_T;
      return _Rmpc_out_str($_[0], $_[1], $_[2], $_[3], $_[4]);
    }
    if(@_ == 6) {
      if(_itsa($_[3]) == _MATH_MPC_T) {return _Rmpc_out_strS($_[0], $_[1], $_[2], $_[3], $_[4], $_[5])}
      die "Incorrect args supplied to Rmpc_out_str" if _itsa($_[4]) != _MATH_MPC_T;
      return _Rmpc_out_strP($_[0], $_[1], $_[2], $_[3], $_[4], $_[5]);
    }
    if(@_ == 7) {
      die "Inappropriate 5th arg supplied to Rmpc_out_str" if _itsa($_[4]) != _MATH_MPC_T;
      return _Rmpc_out_strPS($_[0], $_[1], $_[2], $_[3], $_[4], $_[5], $_[6]);
    }
    die "Wrong number of arguments supplied to Rmpc_out_str()";
}

sub Rmpcb_split {
  if(MPC_HEADER_V >= 66304) { # mpc library is at least version 1.3.0
    my($re, $im, $mpc, $mpcr) = (Math::MPFR->new(), Math::MPFR->new(),
                                 Math::MPC->new(), Rmpcr_init());
    my $mpcb = shift;
    Rmpcb_retrieve($mpc, $mpcr, $mpcb);
    RMPC_RE($re, $mpc);
    RMPC_IM($im, $mpc);
    return($re, $im, $mpcr);
  }
  else {
    die "Rmpcb_split function not implemented - needs mpc-1.3.0 but we have only mpc-", MPC_HEADER_V_STR, "\n";
  }
}

sub Rmpcr_split_mpfr {
  if(MPC_HEADER_V >= 66304) { # mpc library is at least version 1.3.0
    my $r = shift; # mpcr_t object
    if(Rmpcr_zero_p($r)) {
      my $ret = Math::MPFR::Rmpfr_init2(64);
      Math::MPFR::Rmpfr_set_zero($ret, 0);
      return $ret;
    }
    if(Rmpcr_inf_p($r)) {
      return "Inf";
    }

    my $m = Math::MPC::Radius::_get_radius_mantissa($r); # $m is a Math::MPFR object.
    my $e = Math::MPC::Radius::_get_radius_exponent($r); # $e is a Math::MPFR object.

    return($m, $e);
  }
  else {
    die "Rmpcr_split_mpfr function not implemented - needs mpc-1.3.0 but we have only mpc-", MPC_HEADER_V_STR, "\n";
  }
}

sub Rmpc_set_default_rounding_mode {
  # First validate rounding value
  if (MPC_HEADER_V < 66304) {
    die("Illegal rounding value (%d) supplied for this version (%s) of the mpc library", $_[0], MPC_HEADER_V_STR)
      if !_check_rounding_value($_[0]);
  }
  $Math::MPC::DEFAULT_ROUNDING_MODE = shift;
}

sub Rmpc_get_default_rounding_mode {
  return $Math::MPC::DEFAULT_ROUNDING_MODE;
}

sub Rmpc_set_default_prec {
  $Math::MPC::DEFAULT_PREC_RE = shift;
  $Math::MPC::DEFAULT_PREC_IM = $Math::MPC::DEFAULT_PREC_RE;
}

sub Rmpc_set_default_prec2 {
  ($Math::MPC::DEFAULT_PREC_RE, $Math::MPC::DEFAULT_PREC_IM) = (shift, shift);
}

sub Rmpc_get_default_prec {
  return $Math::MPC::DEFAULT_PREC_RE
    if $Math::MPC::DEFAULT_PREC_IM == $Math::MPC::DEFAULT_PREC_RE;
  return 0;
}

sub Rmpc_get_default_prec2 {
  return ($Math::MPC::DEFAULT_PREC_RE, $Math::MPC::DEFAULT_PREC_IM);
}

sub MPC_VERSION            () {return _MPC_VERSION()}
sub MPC_VERSION_MAJOR      () {return _MPC_VERSION_MAJOR()}
sub MPC_VERSION_MINOR      () {return _MPC_VERSION_MINOR()}
sub MPC_VERSION_PATCHLEVEL () {return _MPC_VERSION_PATCHLEVEL()}
sub MPC_VERSION_STRING     () {return _MPC_VERSION_STRING()}
sub MPC_VERSION_NUM           {return _MPC_VERSION_NUM(@_)}

1;

__END__

