use Carp;

#
# find appropriate CFITSIO datatype for a given piddle type.
# Can be passed the piddle itself or a PDL::Type token (e.g.,
# float() with no args).
#
sub match_datatype {

    my $arg = shift;

    my $pdl_type;
    if (UNIVERSAL::isa($arg,'PDL')) {
	$pdl_type = $arg->get_datatype;
    }
    elsif (UNIVERSAL::isa($arg,'PDL::Type')) {
	$pdl_type = $arg->[0];
    }
    else {
	croak "argument should be a PDL object or PDL::Type token";
    }

    my $pdl_size = PDL::Core::howbig($pdl_type);

    my @cfitsio_possible_types;
    # test for real datatypes
    if ($pdl_type == float(1)->get_datatype or
	$pdl_type == double(1)->get_datatype
	)
    {
	@cfitsio_possible_types = (
				 Astro::FITS::CFITSIO::TDOUBLE(),
				 Astro::FITS::CFITSIO::TFLOAT(),
				   );
    }
    elsif ($pdl_type == short(1)->get_datatype or
	   $pdl_type == long(1)->get_datatype
	   )
    {
	@cfitsio_possible_types = (
				 Astro::FITS::CFITSIO::TSHORT(),
				 Astro::FITS::CFITSIO::TINT(),
				 Astro::FITS::CFITSIO::TLONG(),
				   );
    }
    elsif ($pdl_type == ushort(1)->get_datatype or
	   $pdl_type == byte(1)->get_datatype
	   )
    {
	@cfitsio_possible_types = (
				 Astro::FITS::CFITSIO::TBYTE(),
				 Astro::FITS::CFITSIO::TUSHORT(),
				 Astro::FITS::CFITSIO::TUINT(),
				 Astro::FITS::CFITSIO::TULONG(),
				   );
    }
    else
    {
	croak "cannot handle PDL type $pdl_type";
    }


    foreach my $cfitsio_type (@cfitsio_possible_types) {
	return $cfitsio_type if $pdl_size == Astro::FITS::CFITSIO::sizeof_datatype($cfitsio_type);
    }

    croak "no CFITSIO type for PDL type $pdl_type";
}

1;

=head1 match_datatype( )

	$cfitsio_type = match_datatype($piddle);
	$cfitsio_type = match_datatype(long); # or short, or float, etc.

PDL datatypes are always guaranteed to be the same size on all architectures,
whereas CFITSIO datatypes (TLONG, for example), will vary on some
architectures since they correspond to the C datatypes on that system. This
poses a problem for Perl scripts which wish to read FITS data into piddles,
and do so in a portable manner. This routine takes a PDL object or PDL::Types
token (returned by float() and friends when given no arguments), and returns
the same-sized CFITSIO datatype, suitable for passing to routines such as
fits_read_col().

=cut