    package Math::GMPq;
    use strict;
    require Exporter;
    *import = \&Exporter::import;
    require DynaLoader;

    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 subs qw( __GNU_MP_VERSION __GNU_MP_VERSION_MINOR __GNU_MP_VERSION_PATCHLEVEL
             __GMP_CC __GMP_CFLAGS);

use overload
    '+'    => \&overload_add,
    '-'    => \&overload_sub,
    '*'    => \&overload_mul,
    '/'    => \&overload_div,
    '+='   => \&overload_add_eq,
    '-='   => \&overload_sub_eq,
    '*='   => \&overload_mul_eq,
    '/='   => \&overload_div_eq,
    '""'   => \&overload_string,
    '>'    => \&overload_gt,
    '>='   => \&overload_gte,
    '<'    => \&overload_lt,
    '<='   => \&overload_lte,
    '<=>'  => \&overload_spaceship,
    '=='   => \&overload_equiv,
    '!='   => \&overload_not_equiv,
    '!'    => \&overload_not,
    'not'  => \&overload_not,
    '='    => \&overload_copy,
    'int'  => \&overload_int,
    'abs'  => \&overload_abs;

    @Math::GMPq::EXPORT_OK = qw(
__GNU_MP_VERSION __GNU_MP_VERSION_MINOR __GNU_MP_VERSION_PATCHLEVEL
Rmpq_abs Rmpq_add Rmpq_canonicalize Rmpq_clear Rmpq_cmp Rmpq_cmp_si Rmpq_cmp_ui
Rmpq_create_noval Rmpq_denref Rmpq_div Rmpq_div_2exp Rmpq_equal 
Rmpq_fprintf
Rmpq_get_d 
Rmpq_get_den Rmpq_get_num Rmpq_get_str Rmpq_init Rmpq_init_nobless Rmpq_inp_str
Rmpq_inv Rmpq_mul Rmpq_mul_2exp Rmpq_neg Rmpq_numref Rmpq_out_str Rmpq_printf 
Rmpq_set Rmpq_set_d Rmpq_set_den Rmpq_set_f Rmpq_set_num Rmpq_set_si Rmpq_set_str
Rmpq_set_ui Rmpq_set_z Rmpq_sgn 
Rmpq_sprintf Rmpq_sprintf_ret
Rmpq_sub Rmpq_swap
TRmpq_out_str TRmpq_inp_str
    );
    $Math::GMPq::VERSION = '0.28';

    DynaLoader::bootstrap Math::GMPq $Math::GMPq::VERSION;

    %Math::GMPq::EXPORT_TAGS =(mpq => [qw(
Rmpq_abs Rmpq_add Rmpq_canonicalize Rmpq_clear Rmpq_cmp Rmpq_cmp_si Rmpq_cmp_ui
Rmpq_create_noval Rmpq_denref Rmpq_div Rmpq_div_2exp Rmpq_equal 
Rmpq_fprintf
Rmpq_get_d 
Rmpq_get_den Rmpq_get_num Rmpq_get_str Rmpq_init Rmpq_init_nobless Rmpq_inp_str
Rmpq_inv Rmpq_mul Rmpq_mul_2exp Rmpq_neg Rmpq_numref Rmpq_out_str Rmpq_printf 
Rmpq_set Rmpq_set_d Rmpq_set_den Rmpq_set_f Rmpq_set_num Rmpq_set_si Rmpq_set_str
Rmpq_set_ui Rmpq_set_z Rmpq_sgn 
Rmpq_sprintf Rmpq_sprintf_ret
Rmpq_sub Rmpq_swap
TRmpq_out_str TRmpq_inp_str
)]);

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

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::GMPq
    if(!@_) {return Rmpq_init()}
   
    if(@_ > 3) {die "Too many arguments supplied to new()"}

    # If 'new' has been called OOP style, the first arg is the string
    # "Math::GMPq" which we don't need - so let's remove it. However,
    # if the first arg is a Math::GMPq object (which is a possibility),
    # then we'll get a fatal error when we check it for equivalence to
    # the string "Math::GMPq". 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::GMPq") {
      shift;
      if(!@_) {return Rmpq_init()}
      } 

    # @_ can now contain a maximum of 2 args - the value, and iff the value is
    # a string, (optionally) the base of the numeric string.
    if(@_ > 2) {die "Too many arguments supplied to new() - expected no more than two"}

    my ($arg1, $type, $base);

    # $_[0] is the value, $_[1] (if supplied) is the base of the number
    # in the string $[_0].
    $arg1 = shift;
    $base = 0;

    $type = _itsa($arg1);
    if(!$type) {die "Inappropriate argument supplied to new()"}

    my $ret = Rmpq_init();

    # Create a Math::GMPq object that has $arg1 as its value.
    # Die if there are any additional args (unless $type == _POK_T)
    if($type == _UOK_T || $type == _IOK_T) {
      if(@_ ) {die "Too many arguments supplied to new() - expected only one"}
      Rmpq_set_str($ret, $arg1, 10);
      return $ret;
    }

    if($type == _NOK_T) {
      if(@_ ) {die "Too many arguments supplied to new() - expected only one"}
      if(Math::GMPq::_has_longdouble()) {
        _Rmpq_set_ld($ret, $arg1);
        return $ret;
      }
      Rmpq_set_d($ret, $arg1);
      return $ret;
    }
    
    if($type == _POK_T) {
      if(@_ > 1) {die "Too many arguments supplied to new() - expected no more than two"}
      $base = shift if @_;
      if(($base < 2 && $base != 0) || $base > 62) {die "Invalid value for base"}
      Rmpq_set_str($ret, $arg1, $base);
      Rmpq_canonicalize($ret);
      return $ret;
    }

    if($type == _MATH_GMPq_T) { # Math::GMPq object
      if(@_) {die "Too many arguments supplied to new() - expected only one"}
      Rmpq_set($ret, $arg1);
      return $ret;
    }
}

sub Rmpq_out_str {
    if(@_ == 2) {
       die "Inappropriate 1st arg supplied to Rmpq_out_str" if _itsa($_[0]) != _MATH_GMPq_T;
       return _Rmpq_out_str($_[0], $_[1]);
    }
    if(@_ == 3) {
      if(_itsa($_[0]) == _MATH_GMPq_T) {return _Rmpq_out_strS($_[0], $_[1], $_[2])}
      die "Incorrect args supplied to Rmpq_out_str" if _itsa($_[1]) != _MATH_GMPq_T;
      return _Rmpq_out_strP($_[0], $_[1], $_[2]);
    }
    if(@_ == 4) {
      die "Inappropriate 2nd arg supplied to Rmpq_out_str" if _itsa($_[1]) != _MATH_GMPq_T;
      return _Rmpq_out_strPS($_[0], $_[1], $_[2], $_[3]);
    }
    die "Wrong number of arguments supplied to Rmpq_out_str()";
}

sub TRmpq_out_str {
    if(@_ == 3) {
      die "Inappropriate 3rd arg supplied to TRmpq_out_str" if _itsa($_[2]) != _MATH_GMPq_T;
      return _TRmpq_out_str($_[0], $_[1], $_[2]);
    }
    if(@_ == 4) {
      if(_itsa($_[2]) == _MATH_GMPq_T) {return _TRmpq_out_strS($_[0], $_[1], $_[2], $_[3])}
      die "Incorrect args supplied to TRmpq_out_str" if _itsa($_[3]) != _MATH_GMPq_T;
      return _TRmpq_out_strP($_[0], $_[1], $_[2], $_[3]);
    }
    if(@_ == 5) {
      die "Inappropriate 4th arg supplied to TRmpq_out_str" if _itsa($_[3]) != _MATH_GMPq_T;
      return _TRmpq_out_strPS($_[0], $_[1], $_[2], $_[3], $_[4]);
    }
    die "Wrong number of arguments supplied to TRmpq_out_str()";
}

sub _rewrite {
    my $len = length($_[0]);
    my @split = ();
    my @ret = ();
    for(my $i = 0; $i < $len - 1; $i++) {
       if(substr($_[0], $i, 1) eq '%') {
         if(substr($_[0], $i + 1, 1) eq '%') { $i++ }
         else { push(@split, $i) }
         }
       }

    push(@split, $len);
    shift(@split);

    my $start = 0;
    
    for(@split) {
       push(@ret, substr($_[0], $start, $_ - $start));
       $start = $_;
       }

    return @ret;
}

sub Rmpq_printf {
    local $| = 1;
    die "Rmpz_printf must take 2 arguments: format string, and variable" if @_ != 2;
    wrap_gmp_printf(@_);
}

sub Rmpq_fprintf {
    die "Rmpq_fprintf must take 3 arguments: filehandle, format string, and variable" if @_ != 3;
    wrap_gmp_fprintf(@_);
}

sub Rmpq_sprintf {
    die "Rmpq_sprintf must take 3 arguments: buffer, format string, and variable" if @_ != 3;
    my $len = wrap_gmp_sprintf(@_);
    $_[0] = substr($_[0], 0, $len);
    return $len;
}

sub Rmpq_sprintf_ret {
    die "Rmpq_sprintf must take 3 arguments: buffer, format string, and variable" if @_ != 3;
    my $len = wrap_gmp_sprintf(@_);
    return substr($_[0], 0, $len);
}

sub __GNU_MP_VERSION {return ___GNU_MP_VERSION()}
sub __GNU_MP_VERSION_MINOR {return ___GNU_MP_VERSION_MINOR()}
sub __GNU_MP_VERSION_PATCHLEVEL {return ___GNU_MP_VERSION_PATCHLEVEL()}
sub __GMP_CC {return ___GMP_CC()}
sub __GMP_CFLAGS {return ___GMP_CFLAGS()}

1;

__END__

=head1 NAME

   Math::GMPq - perl interface to the GMP library's rational (mpq) functions.
   
=head1 DEPENDENCIES

   This module needs the GMP C library - available from:
   http://gmplib.org.

=head1 DESCRIPTION

   A bigrational module utilising the Gnu MP (GMP) library.
   Basically this module simply wraps all of the 'mpq'
   (rational number) functions provided by that library.
   The documentation below extensively plagiarises the GMP
   documentation (which can be found at http://gmplib.org).
   See also the Math::GMPq test suite for examples of usage.

   IMPORTANT:
    If your perl was built with '-Duse64bitint' you need to assign
    all integers larger than 52-bit in a 'use integer;' block. 
    Failure to do so can result in the creation of the variable as 
    an NV (rather than an IV) - with a resultant loss of precision.

=head1 SYNOPSIS

   use Math::GMPq qw(:mpq);

   my $str = '123542/4'; # numerator = 123542
                         # denominator = 4
   my $base = 10;

   # Create the Math::GMPq object
   my $bn1 = Rmpq_init(); # Value set to 0/1

   # Assign a value.
   Rmpq_set_str($str, $base);

   # Remove any factors common to both numerator and
   # denominator so that gcd(numerator, denominator) == 1.
   Rmpq_canonicalize($bn1);

   # or just use the new() function:
   my $rational = Math::GMPq->new('1234/1179');

   # Perform some operations ... see 'FUNCTIONS' below.

   .
   .

   # print out the value held by $bn1 (in octal):
   print Rmpq_get_str($bn1, 8), "\n"; # prints '170513/2'

   # print out the value held by $bn1 (in decimal):
   print Rmpq_get_str($bn1, 10); # prints '61771/2'.

   # print out the value held by $bn1 (in base 29)
   # using the (alternative) Rmpq_out_str()
   # function. (This function doesn't print a newline.)
   Rmpq_out_str($bn1, 29);

=head1 MEMORY MANAGEMENT

   Objects created with Rmpq_create_init() have been
   blessed into package Math::GMPq. They will 
   therefore be automatically cleaned up by the
   DESTROY() function whenever they go out of scope.

   If you wish, you can create unblessed objects
   with Rmpq_init_nobless().
   It will then be up to you to clean up the memory
   associated with these objects by calling
   Rmpq_clear($op), for each object.
   Alternatively the objects will be cleaned up 
   when the script ends.
   I don't know why you would want to create unblessed
   objects - the point is you can if you want to :-) 

=head1 FUNCTIONS

   See the GMP documentation at http://gmplib.org.

   These next 3 functions are demonstrated above:
   $rop   = Rmpq_init();
   $rop   = Rmpq_set_strl($str, $base); # 1 < $base < 63
   $str = Rmpq_get_str($op, $base); # 1 < $base < 37 

   The following functions are simply wrappers around a GMP
   function of the same name. eg. Rmpq_swap() is a wrapper around
   mpq_swap() which is fully documented in the GMP manual at
   http://gmplib.org.

   "$rop", "$op1", "$op2", etc. are simply  Math::GMPq objects -
   the return value of Rmpq_init or Rmpq_init_nobless
   functions. They are in fact references to GMP structures.
   The "$rop" argument(s) contain the result(s) of the calculation
   being done, the "$op" argument(s) being the input(s) into that 
   calculation.
   Generally, $rop, $op1, $op2, etc. can be the same perl variable,
   though usually they will be distinct perl variables referencing
   distinct GMP structures.
   Eg. something like Rmpq_add($r1, $r1, $r1),
   where $r1 *is* the same reference to the same GMP structure,
   would add $r1 to itself and store the result in $r1. Think of it
   as $r1 += $r1. Otoh, Rmpq_add($r1, $r2, $r3), where each of the
   arguments is a different reference to a different GMP structure
   would add $r2 to $r3 and store the result in $r1. Think of it as
   $r1 = $r2 + $r3. Mostly, the first argument is the argument that 
   stores the result and subsequent arguments provide the input values.
   Exceptions to this can be found in some of the functions that
   actually return a value. 
   Like I say, see the GMP manual for details. I hope it's 
   intuitively obvious or quickly becomes so. Also see the test
   suite that comes with the distro for some examples of usage.

   "$ui" means any integer that will fit into a C 'unsigned long int.

   "$si" means any integer that will fit into a C 'signed long int'.

   "$double" means any number (not necessarily integer) that will fit
   into a C 'double'.

   "$bool" means a value (usually a 'signed long int') in which
   the only interest is whether it evaluates as true or false.

   "$str" simply means a string of symbols that represent a number,
   eg "1234567890987654321234567/7" which might be a base 10 number,
   or "zsa34760sdfgq123r5/11" which would have to represent a base 36
   number (because "z" is a valid digit only in base 36). Valid
   bases for GMP numbers are 2 to 62 (inclusive).

   ############

   CANONICALIZE

   Rmpq_canonicalize($op);
    Remove any factors that are common to the numerator and
    denominator of $op, and make the denominator positive.

   ##########

   INITIALIZE

   Normally, a variable should be initialized once only or at least be
   cleared, using `Rmpq_clear', between initializations.
   'DESTROY' (which calls 'Rmpq_clear') is automatically called on 
   blessed objects whenever they go out of scope.

   See the section 'MEMORY MANAGEMENT' (above).

   $rop = Math::GMPq::new();
   $rop = Math::GMPq->new();
   $rop = new Math::GMPq();
   $rop = Rmpq_init();
   $rop = Rmpq_init_nobless();
    Initialize $rop and set it to 0/1.

   ####################

   ASSIGNMENT FUNCTIONS

   Rmpq_set($rop, $op);
   Rmpq_set_z($rop, $z); # $z is a Math::GMPz object
    Set $rop to value contained in 2nd arg.

   Rmpq_set_ui($rop, $ui1, $ui2);
   Rmpq_set_si($rop, $si1, $si2);
    Set $rop to 2nd arg / 3rd arg.

   Rmpq_set_str($rop, $str, $base);
    Set $rop from $str in the given base $base. The string can be
    an integer like "41" or a fraction like "41/152".  The fraction
    must be in canonical form, or if not then `Rmpq_canonicalize'
    must be called. The numerator and optional denominator are 
    parsed the same as in `Rmpz_set_str'. $base can vary from 2 to
    62, or if $base is 0 then the leading characters are used: `0x'
    for hex, `0' for octal, or decimal otherwise.  Note that this
    is done separately for the numerator and denominator, so for
    instance `0xEF/100' is 239/100, whereas `0xEF/0x100' is 239/256.

   Rmpq_swap($rop1, $rop2);
    Swap the values.

   ####################

   COMBINED INITIALIZATION AND ASSIGNMENT

   NOTE: Do NOT use these functions if $rop has already
   been initialised. Instead use the Rmpq_set* functions 
   in 'Assignment Functions' (above)

   First read the section 'MEMORY MANAGEMENT' (above).

   $rop = Math::GMPq->new($arg);
   $rop = Math::GMPq::new($arg);
   $rop = new Math::GMPq($arg);
    Returns a Math::GMPq object with the value of $arg.
    $arg can be either an integer (signed integer, unsigned
    integer) or a string that represents a numeric value. If $arg is a
    string, an optional additional argument that specifies the base of
    the number can be supplied to new(). If base is 0 (or not supplied)
    then the leading characters are used: 0x or 0X for hex, 0b or 0B
    for binary, 0 for octal, or decimal otherwise. Note that this is
    done separately for the numerator and denominator, so for instance
    0xEF/100 is 239/100, whereas 0xEF/0x100 is 239/256.

   ####################

   RATIONAL CONVERSIONS

   $double = Rmpq_get_d($op);
    Convert $op to a 'double'.

   Rmpq_set_d($rop, $double);
   Rmpq_set_f($rop, $f); # $f is a Math::GnumMPf object
     Set $rop to the value of the 2nd arg, without rounding.

   $str = Rmpq_get_str($op, $base);
    Convert $op to a string of digits in base $base. The base may
    vary from 2 to 36.  The string will be of the form `num/den',
    or if the denominator is 1 then just `num'.

   ###################

   RATIONAL ARITHMETIC

   Rmpq_add($rop, $op1, $op2);
    $rop = $op1 + $op2.

   Rmpq_sub($rop, $op1, $op2);
    $rop = $op1 - $op2.

   Rmpq_mul($rop, $op1, $op2);
    $rop = $op1 * $op2.

   Rmpq_mul_2exp($rop, $op, $ui);
    $rop = $op * (2 ** $ui).

   Rmpq_div($rop, $op1, $op2);
    $rop = $op1 / $op2.

   Rmpq_div_2exp($rop, $op, $ui);
    $rop = $op / (2 ** $ui).

   Rmpq_neg($rop, $op);
    $rop = -$op.

   Rmpq_abs($rop, $op);
    $rop = abs($op).

   Rmpq_inv($rop, $op);
    $rop = 1 / $op.

   ##########################

   APPLYING INTEGER FUNCTIONS

   Rmpq_numref($z, $op); # $z is a Math::GMPz object
   Rmpq_denref($z, $op); # $z is a Math::GMPz object
    Set $rop to the numerator and denominator of $op, respectively.

   Rmpq_get_num($z, $op); # $z is a Math::GMPz oblect
   Rmpq_get_den($z, $op); # $z is a Math::GMPz oblect
   Rmpq_set_num($rop, $z); # $z is a Math::GMPz oblect
   Rmpq_set_den($rop, $z); # $z is a Math::GMPz oblect
    Get or set the numerator or denominator of a rational
    Direct use of `Rmpq_numref' or `Rmpq_denref' is
    recommended instead of these functions.

   ###################

   COMPARING RATIONALS

   $si = Rmpq_cmp($op1, $op2);
    Compare $op1 and $op2.  Return a positive value if $op1 > $op2,
    zero if $op1 = $op2, and a negative value if $op1 < $op2.
    To determine if two rationals are equal, `Rmpq_equal' is
    faster than `Rmpq_cmp'.

   $si = Rmpq_cmp_ui($op, $ui, $ui);
   $si1 = Rmpq_cmp_si($op, $si2, $ui);
    Compare $op1 and 2nd arg/3rd arg.  Return a positive value if
    $op1 > 2nd arg/3rd arg, zero if $op1 = 2nd arg/3rd arg,
    and a negative value if $op1 < 2nd arg/3rd arg.
    2nd and 3rd args are allowed to have common factors.
    Note that the 3rd (NOT 2nd) arg is unsigned. If you want
    to compare $op with 2/-3, make sure that 2nd arg is
    '-2' and 3rd arg is '3'.

   $si = Rmpq_sgn($op);
    Return +1 if $op>0, 0 if $op=0, and -1 if $op<0.

   $bool = Rmpq_equal($op1, $op2); # faster than Rmpq_cmp()
    Return non-zero if $op1 and $op2 are equal, zero if they
    are non-equal.  Although `Rmpq_cmp' can be used for the
    same purpose, this function is much faster.

   ################

   I/O of RATIONALS

   $bytes_written = Rmpq_out_str([$prefix,] $op, $base [, $suffix]);
    BEST TO USE TRmpq_out_str INSTEAD. 
    Output $op to STDOUT, as a string of digits in base $base.
    The base may vary from 2 to 36. Output is in the form `num/den'
    or if the denominator is 1 then just `num'. Return the number
    of bytes written, or if an error occurred, return 0.
    The optional first and last arguments ($prefix and $suffix) are
    strings that will be prepended/appended to the mpq_out_str
    output.  $bytes_written does not include the bytes contained in
    $prefix and $suffix.

   $bytes_written = TRmpq_out_str([$prefix,] $stream, $base, $op, [, $suffix]);
    As for Rmpq_out_str, except that there's the capability to print
    to somewhere other than STDOUT. Note that the order of the args
    is different (to match the order of the mpq_out_str args).
    To print to STDERR:
       TRmpq_out_str(*stderr, $base, $digits, $op);
    To print to an open filehandle (let's call it FH):
       TRmpq_out_str(\*FH, $base, $digits, $op);

   $bytes_read = Rmpq_inp_str($rop, $base);
    BEST TO USE TRmpq_inp_str INSTEAD.
    Read a string of digits from STDIN and convert them to a rational
    in $rop.  Any initial white-space characters are read and
    discarded.  Return the number of characters read (including white
    space), or 0 if a rational could not be read.
    The input can be a fraction like `17/63' or just an integer like
    `123'.  Reading stops at the first character not in this form, and
    white space is not permitted within the string.  If the input
    might not be in canonical form, then `mpq_canonicalize' must be
    called. $base can be between 2 and 36, or can be 0 in which case the
    leading characters of the string determine the base, `0x' or `0X'
    for hexadecimal, `0' for octal, or decimal otherwise.  The leading
    characters are examined separately for the numerator and
    denominator of a fraction, so for instance `0x10/11' is 16/11,
    whereas `0x10/0x11' is 16/17. 

   $bytes_read = TRmpq_inp_str($rop, $stream, $base);
    As for Rmpq_inp_str, except that there's the capability to read
    from somewhere other than STDIN.
    To read from STDIN:
       TRmpq_inp_str($rop, *stdin, $base);
    To read from an open filehandle (let's call it FH):
       TRmpq_inp_str($rop, \*FH, $base);

   ####################

   OPERATOR OVERLOADING 

   Overloading occurs with numbers, strings and Math::GMPq objects.
   Strings are first converted to Math::GMPq objects, then canonicalized.
   See the Rmpq_set_str documentation (above) in the section "ASSIGNMENT
   FUNCTIONS" regarding permissible string formats.
   The following operators are overloaded:
   
    + - * /
    += -= *= /=
    == != ! not
    < <= > >= <=>
    = "" abs

    Atempting to use the overloaded operators with objects that
    have been blessed into some package other than 'Math::GMPq'
    will not work.

    In those situations where the overload subroutine operates on 2
    perl variables, then obviously one of those perl variables is
    a Math::GMPq object. To determine the value of the other variable
    the subroutine works through the following steps (in order),
    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 
       (perl 5.8) the UOK flag is set or if (perl 5.6) SvIsUV() 
       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.)

    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.

    4. If the variable is a string (ie the POK flag is set) then the
       value of that string is used. Octal strings must begin with
       '0', hex strings must begin with either '0x' or '0X' - 
       otherwise the string is assumed to be decimal. If the POK 
       flag is set, but the string is not a valid base 8, 10, or 16
       number, the subroutine croaks with an appropriate error
       message. If the string is of the form 'numerator/denominator',
       then the bases of the numerator and the denominator are 
       assessed individually. ie '0xa123/ff' is not a valid number
       (because 'ff' is not a valid base 10 number). That needs to
       be rewritten as '0xa123/0xff'.

    5. If the variable is a Math::GMPq object then the value of that
       object is used.

    6. If none of the above is true, then the second variable is
       deemed to be of an invalid type. The subroutine croaks with
       an appropriate error message.

   #####

   OTHER

   $GMP_version = Math::GMPq::gmp_v;
    Returns the version of the GMP library (eg 4.1.3). The function
    is not exportable.

   $GMP_cc = Math::GMPq::__GMP_CC;
   $GMP_cflags = Math::GMPq::__GMP_CFLAGS;
    These functions are not exportable.
    If Math::GMPq has been built against gmp-4.2.3 or later,
    returns respectively the CC and CFLAGS settings that were used
    to compile the gmp library.
    Returns undef if Math::GMPq has been built against an earlier
    version of the gmp library. 

   $major = Math::GMPq::__GNU_MP_VERSION;
   $minor = Math::GMPq::__GNU_MP_VERSION_MINOR;
   $patchlevel = Math::GMPq::__GNU_MP_VERSION_PATCHLEVEL;
    Returns respectively the major, minor, and patchlevel numbers
    for the GMP library version used by Math::GMPq. (These 
    functions are in @EXPORT_OK and are therefore exportable by
    request.) 

   ################

   FORMATTED OUTPUT

   NOTE: The format specification can be found at:
   http://gmplib.org/manual/Formatted-Output-Strings.html#Formatted-Output-Strings
   However, the use of '*' to take an extra variable for width and
   precision is not allowed in this implementation. Instead, it is
   necessary to interpolate the variable into the format string - ie,
   instead of:
     Rmpq_printf("%*Zd\n", $width, $mpz);
   we need:
     Rmpq_printf("%${width}Zd\n", $mpz);

   $si = Rmpq_printf($format_string, $var);

    This function changed with the release of Math-GMPq-0.27.
    Now (unlike the GMP counterpart), it is limited to taking 2
    arguments - the format string, and the variable to be formatted.
    That is, you can format only one variable at a time. 
    Returns the number of characters written, or -1 if an error
    occurred.

   $si = Rmpq_fprintf($fh, $format_string, $var);

    This function (unlike the GMP counterpart) is limited to taking
    3 arguments - the filehandle, the format string, and the variable
    to be formatted. That is, you can format only one variable at a time.
    Other than that, the rules outlined above wrt Rmpq_printf apply.
    Returns the number of characters written, or -1 if an error
    occurred.

   $si = Rmpq_sprintf($buffer, $format_string, $var);

    This function (unlike the GMP counterpart) is limited to taking
    3 arguments - the buffer, the format string, and the variable
    to be formatted. $buffer must be large enough to accommodate the
    formatted string, and is truncated to the length of that formatted
    string. If you prefer to have the resultant string returned (rather
    than stored in $buffer), use Rmpq_sprintf_ret instead - which will
    also leave the length of $buffer unaltered.
    Returns the number of characters written, or -1 if an error
    occurred.

   $string = Rmpq_sprintf_ret($buffer, $format_string, $var);

    As for Rmpq_sprintf, but returns the formatted string, rather than
    storing it in $buffer. $buffer needs to be large enough to 
    accommodate the formatted string. The length of $buffer will be
    unaltered.

   ################

=head1 BUGS

    You can get segfaults if you pass the wrong type of
    argument to the functions - so if you get a segfault, the
    first thing to do is to check that the argument types 
    you have supplied are appropriate.

=head1 LICENSE

    This program is free software; you may redistribute it and/or 
    modify it under the same terms as Perl itself.
    Copyright 2006-2008, Sisyphus

=head1 AUTHOR

    Sisyphus <sisyphus at(@) cpan dot (.) org>


=cut