# This file was automatically generated by SWIG (http://www.swig.org).
# Version 3.0.4
#
# Do not make changes to this file unless you know what you are doing--modify
# the SWIG interface file instead.

package Math::GSL::QRNG;
use base qw(Exporter);
use base qw(DynaLoader);
package Math::GSL::QRNGc;
bootstrap Math::GSL::QRNG;
package Math::GSL::QRNG;
@EXPORT = qw();

# ---------- BASE METHODS -------------

package Math::GSL::QRNG;

sub TIEHASH {
    my ($classname,$obj) = @_;
    return bless $obj, $classname;
}

sub CLEAR { }

sub FIRSTKEY { }

sub NEXTKEY { }

sub FETCH {
    my ($self,$field) = @_;
    my $member_func = "swig_${field}_get";
    $self->$member_func();
}

sub STORE {
    my ($self,$field,$newval) = @_;
    my $member_func = "swig_${field}_set";
    $self->$member_func($newval);
}

sub this {
    my $ptr = shift;
    return tied(%$ptr);
}


# ------- FUNCTION WRAPPERS --------

package Math::GSL::QRNG;

*gsl_error = *Math::GSL::QRNGc::gsl_error;
*gsl_stream_printf = *Math::GSL::QRNGc::gsl_stream_printf;
*gsl_strerror = *Math::GSL::QRNGc::gsl_strerror;
*gsl_set_error_handler = *Math::GSL::QRNGc::gsl_set_error_handler;
*gsl_set_error_handler_off = *Math::GSL::QRNGc::gsl_set_error_handler_off;
*gsl_set_stream_handler = *Math::GSL::QRNGc::gsl_set_stream_handler;
*gsl_set_stream = *Math::GSL::QRNGc::gsl_set_stream;
*gsl_qrng_alloc = *Math::GSL::QRNGc::gsl_qrng_alloc;
*gsl_qrng_memcpy = *Math::GSL::QRNGc::gsl_qrng_memcpy;
*gsl_qrng_clone = *Math::GSL::QRNGc::gsl_qrng_clone;
*gsl_qrng_free = *Math::GSL::QRNGc::gsl_qrng_free;
*gsl_qrng_init = *Math::GSL::QRNGc::gsl_qrng_init;
*gsl_qrng_name = *Math::GSL::QRNGc::gsl_qrng_name;
*gsl_qrng_size = *Math::GSL::QRNGc::gsl_qrng_size;
*gsl_qrng_state = *Math::GSL::QRNGc::gsl_qrng_state;
*gsl_qrng_get = *Math::GSL::QRNGc::gsl_qrng_get;

############# Class : Math::GSL::QRNG::gsl_qrng_type ##############

package Math::GSL::QRNG::gsl_qrng_type;
use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
@ISA = qw( Math::GSL::QRNG );
%OWNER = ();
%ITERATORS = ();
*swig_name_get = *Math::GSL::QRNGc::gsl_qrng_type_name_get;
*swig_name_set = *Math::GSL::QRNGc::gsl_qrng_type_name_set;
*swig_max_dimension_get = *Math::GSL::QRNGc::gsl_qrng_type_max_dimension_get;
*swig_max_dimension_set = *Math::GSL::QRNGc::gsl_qrng_type_max_dimension_set;
*swig_state_size_get = *Math::GSL::QRNGc::gsl_qrng_type_state_size_get;
*swig_state_size_set = *Math::GSL::QRNGc::gsl_qrng_type_state_size_set;
*swig_init_state_get = *Math::GSL::QRNGc::gsl_qrng_type_init_state_get;
*swig_init_state_set = *Math::GSL::QRNGc::gsl_qrng_type_init_state_set;
*swig_get_get = *Math::GSL::QRNGc::gsl_qrng_type_get_get;
*swig_get_set = *Math::GSL::QRNGc::gsl_qrng_type_get_set;
sub new {
    my $pkg = shift;
    my $self = Math::GSL::QRNGc::new_gsl_qrng_type(@_);
    bless $self, $pkg if defined($self);
}

sub DESTROY {
    return unless $_[0]->isa('HASH');
    my $self = tied(%{$_[0]});
    return unless defined $self;
    delete $ITERATORS{$self};
    if (exists $OWNER{$self}) {
        Math::GSL::QRNGc::delete_gsl_qrng_type($self);
        delete $OWNER{$self};
    }
}

sub DISOWN {
    my $self = shift;
    my $ptr = tied(%$self);
    delete $OWNER{$ptr};
}

sub ACQUIRE {
    my $self = shift;
    my $ptr = tied(%$self);
    $OWNER{$ptr} = 1;
}


############# Class : Math::GSL::QRNG::gsl_qrng ##############

package Math::GSL::QRNG::gsl_qrng;
use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
@ISA = qw( Math::GSL::QRNG );
%OWNER = ();
%ITERATORS = ();
sub DESTROY {
    return unless $_[0]->isa('HASH');
    my $self = tied(%{$_[0]});
    return unless defined $self;
    delete $ITERATORS{$self};
    if (exists $OWNER{$self}) {
        Math::GSL::QRNGc::delete_gsl_qrng($self);
        delete $OWNER{$self};
    }
}

*swig_type_get = *Math::GSL::QRNGc::gsl_qrng_type_get;
*swig_type_set = *Math::GSL::QRNGc::gsl_qrng_type_set;
*swig_dimension_get = *Math::GSL::QRNGc::gsl_qrng_dimension_get;
*swig_dimension_set = *Math::GSL::QRNGc::gsl_qrng_dimension_set;
*swig_state_size_get = *Math::GSL::QRNGc::gsl_qrng_state_size_get;
*swig_state_size_set = *Math::GSL::QRNGc::gsl_qrng_state_size_set;
*swig_state_get = *Math::GSL::QRNGc::gsl_qrng_state_get;
*swig_state_set = *Math::GSL::QRNGc::gsl_qrng_state_set;
sub new {
    my $pkg = shift;
    my $self = Math::GSL::QRNGc::new_gsl_qrng(@_);
    bless $self, $pkg if defined($self);
}

sub DISOWN {
    my $self = shift;
    my $ptr = tied(%$self);
    delete $OWNER{$ptr};
}

sub ACQUIRE {
    my $self = shift;
    my $ptr = tied(%$self);
    $OWNER{$ptr} = 1;
}


# ------- VARIABLE STUBS --------

package Math::GSL::QRNG;

*GSL_MAJOR_VERSION = *Math::GSL::QRNGc::GSL_MAJOR_VERSION;
*GSL_MINOR_VERSION = *Math::GSL::QRNGc::GSL_MINOR_VERSION;
*GSL_POSZERO = *Math::GSL::QRNGc::GSL_POSZERO;
*GSL_NEGZERO = *Math::GSL::QRNGc::GSL_NEGZERO;
*GSL_SUCCESS = *Math::GSL::QRNGc::GSL_SUCCESS;
*GSL_FAILURE = *Math::GSL::QRNGc::GSL_FAILURE;
*GSL_CONTINUE = *Math::GSL::QRNGc::GSL_CONTINUE;
*GSL_EDOM = *Math::GSL::QRNGc::GSL_EDOM;
*GSL_ERANGE = *Math::GSL::QRNGc::GSL_ERANGE;
*GSL_EFAULT = *Math::GSL::QRNGc::GSL_EFAULT;
*GSL_EINVAL = *Math::GSL::QRNGc::GSL_EINVAL;
*GSL_EFAILED = *Math::GSL::QRNGc::GSL_EFAILED;
*GSL_EFACTOR = *Math::GSL::QRNGc::GSL_EFACTOR;
*GSL_ESANITY = *Math::GSL::QRNGc::GSL_ESANITY;
*GSL_ENOMEM = *Math::GSL::QRNGc::GSL_ENOMEM;
*GSL_EBADFUNC = *Math::GSL::QRNGc::GSL_EBADFUNC;
*GSL_ERUNAWAY = *Math::GSL::QRNGc::GSL_ERUNAWAY;
*GSL_EMAXITER = *Math::GSL::QRNGc::GSL_EMAXITER;
*GSL_EZERODIV = *Math::GSL::QRNGc::GSL_EZERODIV;
*GSL_EBADTOL = *Math::GSL::QRNGc::GSL_EBADTOL;
*GSL_ETOL = *Math::GSL::QRNGc::GSL_ETOL;
*GSL_EUNDRFLW = *Math::GSL::QRNGc::GSL_EUNDRFLW;
*GSL_EOVRFLW = *Math::GSL::QRNGc::GSL_EOVRFLW;
*GSL_ELOSS = *Math::GSL::QRNGc::GSL_ELOSS;
*GSL_EROUND = *Math::GSL::QRNGc::GSL_EROUND;
*GSL_EBADLEN = *Math::GSL::QRNGc::GSL_EBADLEN;
*GSL_ENOTSQR = *Math::GSL::QRNGc::GSL_ENOTSQR;
*GSL_ESING = *Math::GSL::QRNGc::GSL_ESING;
*GSL_EDIVERGE = *Math::GSL::QRNGc::GSL_EDIVERGE;
*GSL_EUNSUP = *Math::GSL::QRNGc::GSL_EUNSUP;
*GSL_EUNIMPL = *Math::GSL::QRNGc::GSL_EUNIMPL;
*GSL_ECACHE = *Math::GSL::QRNGc::GSL_ECACHE;
*GSL_ETABLE = *Math::GSL::QRNGc::GSL_ETABLE;
*GSL_ENOPROG = *Math::GSL::QRNGc::GSL_ENOPROG;
*GSL_ENOPROGJ = *Math::GSL::QRNGc::GSL_ENOPROGJ;
*GSL_ETOLF = *Math::GSL::QRNGc::GSL_ETOLF;
*GSL_ETOLX = *Math::GSL::QRNGc::GSL_ETOLX;
*GSL_ETOLG = *Math::GSL::QRNGc::GSL_ETOLG;
*GSL_EOF = *Math::GSL::QRNGc::GSL_EOF;

my %__gsl_qrng_niederreiter_2_hash;
tie %__gsl_qrng_niederreiter_2_hash,"Math::GSL::QRNG::gsl_qrng_type", $Math::GSL::QRNGc::gsl_qrng_niederreiter_2;
$gsl_qrng_niederreiter_2= \%__gsl_qrng_niederreiter_2_hash;
bless $gsl_qrng_niederreiter_2, Math::GSL::QRNG::gsl_qrng_type;

my %__gsl_qrng_sobol_hash;
tie %__gsl_qrng_sobol_hash,"Math::GSL::QRNG::gsl_qrng_type", $Math::GSL::QRNGc::gsl_qrng_sobol;
$gsl_qrng_sobol= \%__gsl_qrng_sobol_hash;
bless $gsl_qrng_sobol, Math::GSL::QRNG::gsl_qrng_type;

my %__gsl_qrng_halton_hash;
tie %__gsl_qrng_halton_hash,"Math::GSL::QRNG::gsl_qrng_type", $Math::GSL::QRNGc::gsl_qrng_halton;
$gsl_qrng_halton= \%__gsl_qrng_halton_hash;
bless $gsl_qrng_halton, Math::GSL::QRNG::gsl_qrng_type;

my %__gsl_qrng_reversehalton_hash;
tie %__gsl_qrng_reversehalton_hash,"Math::GSL::QRNG::gsl_qrng_type", $Math::GSL::QRNGc::gsl_qrng_reversehalton;
$gsl_qrng_reversehalton= \%__gsl_qrng_reversehalton_hash;
bless $gsl_qrng_reversehalton, Math::GSL::QRNG::gsl_qrng_type;


use strict;
use warnings;
use Carp qw/croak/;
use Math::GSL::Errno qw/$GSL_SUCCESS/;

our @EXPORT_OK = qw($gsl_qrng_niederreiter_2 $gsl_qrng_sobol
                    $gsl_qrng_halton $gsl_qrng_reversehalton
                gsl_qrng_alloc gsl_qrng_memcpy gsl_qrng_clone
                gsl_qrng_free  gsl_qrng_init gsl_qrng_name
                gsl_qrng_size gsl_qrng_state gsl_qrng_get
            );
our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );

=encoding utf8

=head1 NAME

Math::GSL::QRNG - Quasi-random number generators

=head1 SYNOPSIS

    # use OO approach
    use Math::GSL::QRNG;

    my $QRNG = Math::GSL::QRNG::Sobol->new(2);
    my @samples = $QRNG->get();

    # use GSL interface
    use Math::GSL::QRNG qw/:all/;

=head1 DESCRIPTION

This module interfaces with GNU Scientific Library quasi-random number generators (QRNG).

=head1 OO Interface

The OO Interface described in this documentation is available to all
different subclasses, namely:

=over

=item Math::GSL::QRNG::Sobol

=item Math::GSL::QRNG::Niederreiter2

=item Math::GSL::QRNG::Halton

=item Math::GSL::QRNG::ReverseHalton

=back

=cut

sub _init {
	my ($self, $qrng, $dimension) = @_;
	$self->{qrng} = gsl_qrng_alloc($qrng, $dimension);
	return $self;
}

=head2 reinit

Reinitializes the generator to its starting point. Note that quasi-random
sequences do not use a seed and always produce the same set of values.

	$qrng->reinit();

=cut

sub reinit {
	my $self = shift;
	gsl_qrng_init($self->{qrng});
}

=head2 get

Retrieves the next point from the sequence generator.
Returns C<undef> on error.

	my @points = $qrng->get();

=cut

sub get {
	my $self = shift;
	my ($status, @values) = gsl_qrng_get($self->{qrng});
	return $status == $GSL_SUCCESS ? @values : undef;
}

=head2 name

Retrieves the QRNG name.

    my $name = $qrng->name();

=cut

sub name {
	my $self = shift;
	return gsl_qrng_name($self->{qrng});
}

=head2 state_size

Returns the size of the QRNG state.

=cut

sub state_size {
	my $self = shift;
	return gsl_qrng_size($self->{qrng});
}

=head2 clone

Returns an exact copy of the current QRNG.

=cut

sub clone {
	my $self = shift;
	my $new = { qrng => gsl_qrng_clone($self->{qrng})};
	return bless $new, ref($self);
}

### gsl_qrng_state => TODO
### gsl_qrng_memcpy => ignore?

=head1 GSL API

Here is a list of all the functions included in this module :

=over

=item C<gsl_qrng_alloc($T, $n)> - This function returns a pointer to a newly-created instance of a quasi-random sequence generator of type $T and dimension $d. The type $T must be one of the constants included in this module.

=item C<gsl_qrng_clone($q)> - This function returns a pointer to a newly created generator which is an exact copy of the generator $q.

=item C<gsl_qrng_memcpy($dest, $src)> - This function copies the quasi-random sequence generator $src into the pre-existing generator $dest, making $dest into an exact copy of $src. The two generators must be of the same type.

=item C<gsl_qrng_free($q)> - This function frees all the memory associated with the generator $q.
Don't call this function explicitly. It will be called automatically in DESTROY.

=item C<gsl_qrng_init($q)> - This function reinitializes the generator $q to its starting point. Note that quasi-random sequences do not use a seed and always produce the same set of values.

=item C<gsl_qrng_name($q)> - This function returns a pointer to the name of the generator $q.

=item C<gsl_qrng_size($q)> - This function returns the size of the state of generator r from the generator $q. You can use this information to access the state directly.

=item C<gsl_qrng_state($q)> - This function returns a pointer to the state of generator r from the generator $q. You can use this information to access the state directly.

=item C<gsl_qrng_get>

=back

This module also contains the following constants :

=over

=item C<$gsl_qrng_niederreiter_2>

=item C<$gsl_qrng_sobol>

=item C<$gsl_qrng_halton>

=item C<$gsl_qrng_reversehalton>

=back

For more informations on the functions, we refer you to the GSL offcial documentation: L<http://www.gnu.org/software/gsl/manual/html_node/>




=head1 EXAMPLES

=head1 AUTHORS

Jonathan "Duke" Leto <jonathan@leto.net>
Thierry Moisan <thierry.moisan@gmail.com>
Alberto Simões <ambs@cpan.org>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2008-2014 Jonathan "Duke" Leto and Thierry Moisan

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=cut


package Math::GSL::QRNG::Sobol;
use parent 'Math::GSL::QRNG';
sub new {
	my ($class, $dimension) = @_;

	croak (__PACKAGE__.'::new($d) - supported dimensions are positive up to 40.')
		if $dimension < 1 or $dimension > 40;

	my $self = bless {}, $class;
	$self->SUPER::_init($Math::GSL::QRNG::gsl_qrng_sobol, $dimension);
	return $self;
}

# gsl_qrng_halton

package Math::GSL::QRNG::Halton;
use parent 'Math::GSL::QRNG';
sub new {
	my ($class, $dimension) = @_;

	croak (__PACKAGE__.'::new($d) - supported dimensions are positive up to 1229.')
		if $dimension < 1 or $dimension > 1229;

	my $self = bless {}, $class;
	$self->SUPER::_init($Math::GSL::QRNG::gsl_qrng_halton, $dimension);
	return $self;
}

# gsl_qrng_reversehalton
package Math::GSL::QRNG::ReverseHalton;
use parent 'Math::GSL::QRNG';
sub new {
	my ($class, $dimension) = @_;

	croak (__PACKAGE__.'::new($d) - supported dimensions are positive up to 1229.')
		if $dimension < 1 or $dimension > 1229;

	my $self = bless {}, $class;
	$self->SUPER::_init($Math::GSL::QRNG::gsl_qrng_reversehalton, $dimension);
	return $self;
}

# gsl_qrng_niederreiter_2
package Math::GSL::QRNG::Niederreiter2;
use parent 'Math::GSL::QRNG';
sub new {
	my ($class, $dimension) = @_;

	croak (__PACKAGE__.'::new($d) - supported dimensions are positive up to 12.')
		if $dimension < 1 or $dimension > 12;

	my $self = bless {}, $class;
	$self->SUPER::_init($Math::GSL::QRNG::gsl_qrng_niederreiter_2, $dimension);
	return $self;
}

__END__


1;
