Data-MATFile
view release on metacpan or search on metacpan
lib/Data/MATFile.pm view on Meta::CPAN
my $n = n_from_dim (\@dim);
Given the dimensions of a matrix, return the total number of
elements in the matrix.
=cut
sub n_from_dim
{
my ($dim) = @_;
my $n = 1;
for (@$dim) {
$n *= $_;
}
return $n;
}
=head2 get_doubles
my $doubles = $obj->get_doubles ($n_bytes);
Get C<$n_bytes / 8> doubles and put them in an array.
=cut
sub get_doubles
{
my ($obj, $n_bytes) = @_;
if ($n_bytes % 8 != 0) {
$obj->error ("Bad byte count $n_bytes for doubles");
}
my $n_doubles = $n_bytes / 8;
my $bytes = $obj->read_bytes ($n_bytes);
my @doubles;
for (0..$n_doubles - 1) {
my $double = parse_double (substr ($bytes, $_ * 8, 8));
if ($obj->{verbose}) {
printf "Got a $double.\n";
}
push @doubles, $double;
}
return \@doubles;
}
=head2 parse_double
my $double = parse_double ($bytes);
This converts the MAT-File double (eight bytes, the IEEE 754 "double
64" format) into a Perl floating point number.
=cut
# http://www.perlmonks.org/bare/?node_id=703222
sub double_from_hex { unpack 'd', scalar reverse pack 'H*', $_[0] }
use constant POS_INF => double_from_hex '7FF0000000000000';
use constant NEG_INF => double_from_hex 'FFF0000000000000';
use constant NaN => double_from_hex '7FF8000000000000';
sub parse_double
{
my ($bytes) = @_;
my ($bottom, $top) = unpack ("LL", $bytes);
# Reference:
# http://en.wikipedia.org/wiki/Double_precision_floating-point_format
# Eight zero bytes represents 0.0.
if ($bottom == 0) {
if ($top == 0) {
return 0;
}
elsif ($top == 0x80000000) {
return -0;
}
elsif ($top == 0x7ff00000) {
return POS_INF;
}
elsif ($top == 0xfff00000) {
return NEG_INF;
}
}
elsif ($top == 0x7ff00000) {
return NaN;
}
my $sign = $top >> 31;
# print "$sign\n";
my $exponent = (($top >> 20) & 0x7FF) - 1023;
# print "$exponent\n";
my $e = ($top >> 20) & 0x7FF;
my $t = $top & 0xFFFFF;
# printf ("--> !%011b%020b \n--> %032b\n", $e, $t, $top);
my $mantissa = ($bottom + ($t*(2**32))) / 2**52 + 1;
# print "$mantissa\n";
my $double = (-1)**$sign * 2**$exponent * $mantissa;
return $double;
}
=head2 get_array_name
my $name = $obj->get_array_name ();
Get the name of an array from the next point in the file. If the array
does not have a name, the return value is the undefined value.
=cut
sub get_array_name
{
my ($obj) = @_;
if ($obj->{verbose}) {
print "Trying to read the array's name.\n";
}
my ($type, $n_bytes, $data) = $obj->read_data_header ();
if ($type != miINT8) {
$obj->error ("bad type $type for array name");
}
# Arrays within a struct have name fields with zero bytes.
if ($n_bytes == 0) {
return undef;
}
if (! $data) {
$data = $obj->read_bytes ($n_bytes);
}
# Remove trailing bytes from the string.
$data = substr $data, 0, $n_bytes;
if ($obj->{verbose}) {
print "The array's name is \"$data\".\n";
}
return $data;
}
=head2 get_array_dimensions
my @dim = $obj->get_array_dimensions ();
Get the dimensions of an array from the file, as an array. Matlab
arrays always have at least two dimensions, so @dim is at least size
2.
=cut
sub get_array_dimensions
{
( run in 1.817 second using v1.01-cache-2.11-cpan-140bd7fdf52 )