The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# --8<--8<--8<--8<--
#
# Copyright (C) 2012 Smithsonian Astrophysical Observatory
#
# This file is part of Math::Rational::Approx::MaxD
#
# Math::Rational::Approx::MaxD is free software: you can redistribute
# it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, either version
# 3 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# -->8-->8-->8-->8--

package Math::Rational::Approx::MaxD;

use strict;
use warnings;
use Carp;


our $VERSION = '0.01';

use Params::Validate qw[ validate_pos ARRAYREF ];
use Math::Rational::Approx;

use Moo;
use MooX::Types::MooseLike::Numeric ':all';
use MooX::Types::MooseLike::Base ':all';

has x => (
  is  => 'ro',
  isa => PositiveNum,
  required => 1,
);

has maxD => (
  is  => 'rwp',
  isa => PositiveInt,
  required => 1,
);

has bounds => (
  is => 'ro',
  coerce => sub { return  is_ArrayRef($_[0]) ? [ @{$_[0]} ] : $_[0] },
  isa => ArrayRef[PositiveOrZeroInt],
  default => sub { [] },
);

sub BUILD {

	my $self = shift;

	Math::Rational::Approx::_check_bounds( $self->x, $self->bounds )
	  if @{$self->bounds};
}


sub approx {

	my $self = shift;

	my ( $maxD ) = validate_pos( @_,
	                           { callbacks => { 'positive integer' => sub { is_PositiveInt($_[0]) } },
	                             optional => 1,
	                           }
	                             );
	$self->_set_maxD( $maxD )
	  if defined $maxD && $maxD > $self->maxD;

	my ( $n, $d ) = Math::Rational::Approx::maxD( $self->x, $self->maxD, $self->bounds );

	return ( $n, $d );
}

1;



__END__

=head1 NAME

Math::Rational::Approx::MaxD - approximate a number with a rational number up to a given denominator


=head1 SYNOPSIS

    use Math::Rational::Approx::MaxD;

    # approximate up to denominator of 10
    $rat = Math::Rational::Approx::MaxD->new( x => $x, maxD => 10 );

    ($n, $d ) = $rat->approx;

    # approximate up to denominator of 20
    ($n, $d ) = $rat->approx( 20 );


=head1 DESCRIPTION

This module is an object oriented front end to the
B<Math::Rational::Approx::maxd> function

=head1 INTERFACE

=over

=item new

    $obj = Math::Rational::Approx::MaxD->new( %attr );

Create a new object.  The following attributes are available

=over

=item C<x>

The number to approximate.

=item C<maxD>

The limiting maximum denominator to check;

=item C<bounds>

I<Optional>. A reference to a four element array containing the
initial bounds on the region to search.  It takes the form

  bounds => [ a, b, c, d ]

where the elements are all non-negative integers and the bounds are
given by

  a/b < x < c/d

By default it searches from C<float(x)> to C<float(x)+1>.

=back

=item approx

  ( $n, $d ) = $obj->approx;
  ( $n, $d ) = $obj->approx( $maxD );

Return the nominator and denominator for a given maximum value of the
denominator.  If C<$maxD> is not specified it is that specified in the
call to the constructor or in any subsequent call to approx.  New
values of C<$maxD> less than one already specified are ignored.

=item bounds

  $bounds = $obj->bounds;

Return an arrayref which contains the current bounds on the search,
in the same format as the C<bounds> attribute passed to B<new>.

=item x

  $x = $obj->x;

The original number to be approximated.

=item maxD

The current value of the maximum denominator.

=back

=head1 DEPENDENCIES

L<Moo>, L<MooX::Types::MooseLike>, L<Params::Validate>, L<Math::Rational::Approx>.


=head1 INCOMPATIBILITIES

None reported.


=head1 BUGS AND LIMITATIONS

No bugs have been reported.

Please report any bugs or feature requests to
C<bug-math-rational-approx@rt.cpan.org>, or through the web interface at
L<http://rt.cpan.org/Public/Dist/Display.html?Name=Math-Rational-Approx>.

=head1 SEE ALSO

L<Math::Rational::Approx>

=head1 AUTHOR

Diab Jerius  E<lt>djerius@cpan.orgE<gt>

=head1 LICENSE AND COPYRIGHT

Copyright (c) 2012 The Smithsonian Astrophysical Observatory

Math::Rational::Approx is free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.