The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Math::BigRat::Test;

require 5.006;
use strict;
use warnings;

use Exporter;
use Math::BigRat;
use Math::BigFloat;

our @ISA = qw(Math::BigRat Exporter);
our $VERSION = '0.04';

use overload; 		# inherit overload from BigRat

# Globals
our $accuracy   = undef;
our $precision  = undef;
our $round_mode = 'even';
our $div_scale  = 40;

my $class = 'Math::BigRat::Test';

#sub new {
#    my $proto  = shift;
#    my $class  = ref($proto) || $proto;
#
#    my $value       = shift;
#    my $a = $accuracy; $a = $_[0] if defined $_[0];
#    my $p = $precision; $p = $_[1] if defined $_[1];
#    # Store the floating point value
#    my $self = Math::BigFloat->new($value, $a, $p, $round_mode);
#    bless $self, $class;
#    $self->{'_custom'} = 1;     # make sure this never goes away
#    return $self;
#}

BEGIN {
    *fstr  = \&bstr;
    *fsstr = \&bsstr;
    *objectify = \&Math::BigInt::objectify;
    *AUTOLOAD  = \&Math::BigRat::AUTOLOAD;
    no strict 'refs';
    foreach my $method (qw/div acmp floor ceil root sqrt log fac modpow modinv/) {
        *{'b' . $method} = \&{'Math::BigRat::b' . $method};
    }
}

sub fround {
    my ($x, $a) = @_;

    #print "$a $accuracy $precision $round_mode\n";
    Math::BigFloat->round_mode($round_mode);
    Math::BigFloat->accuracy($a || $accuracy);
    Math::BigFloat->precision(undef);
    my $y = Math::BigFloat->new($x->bsstr(), undef, undef);
    $class->new($y->fround($a));
}

sub ffround {
    my ($x, $p) = @_;

    Math::BigFloat->round_mode($round_mode);
    Math::BigFloat->accuracy(undef);
    Math::BigFloat->precision($p || $precision);
    my $y = Math::BigFloat->new($x->bsstr(), undef, undef);
    $class->new($y->ffround($p));
}

sub bstr {
    # calculate a BigFloat compatible string output
    my ($x) = @_;

    $x = $class->new($x) unless ref $x;

    if ($x->{sign} !~ /^[+-]$/) { # inf, NaN etc
        my $s = $x->{sign};
        $s =~ s/^\+//;          # +inf => inf
        return $s;
    }

    my $s = '';
    $s = $x->{sign} if $x->{sign} ne '+'; # +3 vs 3

    #  print " bstr \$x ", $accuracy || $x->{_a} || 'notset', " ", $precision || $x->{_p} || 'notset', "\n";
    return $s.$x->{_n} if $x->{_d}->is_one();
    my $output = Math::BigFloat->new($x->{_n})->bdiv($x->{_d});
    local $Math::BigFloat::accuracy  = $accuracy  || $x->{_a};
    local $Math::BigFloat::precision = $precision || $x->{_p};
    $s.$output->bstr();
}

sub numify {
    $_[0]->bsstr();
}

sub bsstr {
    # calculate a BigFloat compatible string output
    my ($x) = @_;

    $x = $class->new($x) unless ref $x;

    if ($x->{sign} !~ /^[+-]$/) {       # inf, NaN etc
        my $s = $x->{sign};
        $s =~ s/^\+//;                  # +inf => inf
        return $s;
    }

    my $s = '';
    $s = $x->{sign} if $x->{sign} ne '+'; # +3 vs 3

    my $output = Math::BigFloat->new($x->{_n})->bdiv($x->{_d});
    return $s.$output->bsstr();
}

1;