AI-TensorFlow-Libtensorflow
view release on metacpan or search on metacpan
lib/AI/TensorFlow/Libtensorflow/Tensor.pm view on Meta::CPAN
package AI::TensorFlow::Libtensorflow::Tensor;
# ABSTRACT: A multi-dimensional array of elements of a single data type
$AI::TensorFlow::Libtensorflow::Tensor::VERSION = '0.0.7';
use strict;
use warnings;
use namespace::autoclean;
use AI::TensorFlow::Libtensorflow::Lib qw(arg);
use FFI::Platypus::Closure;
use FFI::Platypus::Buffer qw(window);
use List::Util qw(product);
my $ffi = AI::TensorFlow::Libtensorflow::Lib->ffi;
$ffi->mangler(AI::TensorFlow::Libtensorflow::Lib->mangler_default);
$ffi->load_custom_type('AI::TensorFlow::Libtensorflow::Lib::FFIType::TFPtrSizeScalarRef'
=> 'tf_tensor_buffer'
);
$ffi->attach( [ 'NewTensor' => 'New' ] =>
[
arg 'TF_DataType' => 'dtype',
# const int64_t* dims, int num_dims
arg 'tf_dims_buffer' => [ qw(dims num_dims) ],
# void* data, size_t len
arg 'tf_tensor_buffer' => [ qw(data len) ],
arg 'opaque' => 'deallocator', # tensor_deallocator_t (deallocator)
arg 'opaque' => 'deallocator_arg',
],
=> 'TF_Tensor' => sub {
my ($xs, $class,
$dtype, $dims, $data,
$deallocator, $deallocator_arg,
) = @_;
my $deallocator_closure = $ffi->closure( $deallocator );
$deallocator_closure->sticky;
my $deallocator_ptr = $ffi->cast(
'tensor_deallocator_t', 'opaque',
$deallocator_closure );
my $obj = $xs->(
$dtype,
$dims,
$data,
$deallocator_ptr, $deallocator_arg,
);
# Return early if no TF_Tensor created
# TODO should this throw an exception instead?
return unless $obj;
$obj->{_deallocator_closure} = $deallocator_closure;
$obj;
});
# C: TF_AllocateTensor
#
# Constructor
$ffi->attach( [ 'AllocateTensor', 'Allocate' ],
[
arg 'TF_DataType' => 'dtype',
arg 'tf_dims_buffer' => [ qw(dims num_dims) ],
arg 'size_t' => 'len',
],
=> 'TF_Tensor' => sub {
my ($xs, $class, @rest) = @_;
my ($dtype, $dims, $len) = @rest;
if( ! defined $len ) {
$len = product($dtype->Size, @$dims);
}
my $obj = $xs->($dtype, $dims, $len);
}
);
$ffi->attach( [ 'DeleteTensor' => 'DESTROY' ],
[ arg 'TF_Tensor' => 't' ]
=> 'void'
=> sub {
my ($xs, $self) = @_;
$xs->($self);
if( exists $self->{_deallocator_closure} ) {
$self->{_deallocator_closure}->unstick;
}
}
);
$ffi->attach( [ 'TensorData' => 'Data' ],
[ arg 'TF_Tensor' => 'self' ],
=> 'opaque'
=> sub {
my ($xs, @rest) = @_;
my ($self) = @rest;
my $data_p = $xs->(@rest);
window(my $buffer, $data_p, $self->ByteSize);
\$buffer;
}
);
$ffi->attach( [ 'TensorByteSize' => 'ByteSize' ],
[ arg 'TF_Tensor' => 'self' ],
=> 'size_t'
);
$ffi->attach( [ 'TensorType' => 'Type' ],
[ arg 'TF_Tensor' => 'self' ],
=> 'TF_DataType'
);
$ffi->attach( [ 'NumDims' => 'NumDims' ],
[ arg 'TF_Tensor' => 'self' ],
=> 'int',
);
$ffi->attach( [ 'TensorElementCount' => 'ElementCount' ] =>
[ arg 'TF_Tensor' => 'self' ]
=> 'int64_t'
);
$ffi->attach( [ 'Dim' => 'Dim' ],
[
arg 'TF_Tensor' => 't',
arg 'int' => 'dim_index',
],
=> 'int64_t',
);
$ffi->attach( [ 'TensorMaybeMove' => 'MaybeMove' ] =>
[ arg 'TF_Tensor' => 'self' ],
=> 'TF_Tensor',
);
$ffi->attach( ['TensorIsAligned' => 'IsAligned'] => [
arg TF_Tensor => 't'
] => 'bool' );
eval {# TF v2.10.0
$ffi->attach( [ 'SetShape' => 'SetShape' ] =>
[
arg 'TF_Tensor' => 'self',
arg 'tf_dims_buffer' => [ qw(dims num_dims) ],
]
=> 'void'
);
};
$ffi->attach( [ 'TensorBitcastFrom' => 'BitcastFrom' ] => [
arg TF_Tensor => 'from',
arg TF_DataType => 'type',
arg TF_Tensor => 'to',
arg 'tf_dims_buffer' => [ qw(new_dims num_new_dims) ],
arg TF_Status => 'status',
] => 'void' );
#### Array helpers ####
use FFI::C::ArrayDef;
use FFI::C::StructDef;
my $adef = FFI::C::ArrayDef->new(
$ffi,
name => 'TF_Tensor_array',
members => [
FFI::C::StructDef->new(
$ffi,
members => [
p => 'opaque'
]
)
],
);
sub _adef {
$adef;
}
sub _as_array {
my $class = shift;
my $array = $class->_adef->create(0 + @_);
for my $idx (0..@_-1) {
next unless defined $_[$idx];
$array->[$idx]->p($ffi->cast('TF_Tensor', 'opaque', $_[$idx]));
}
$array;
}
sub _from_array {
my ($class, $array) = @_;
return [
map {
$ffi->cast(
'opaque',
'TF_Tensor',
$array->[$_]->p)
} 0.. $array->count - 1
]
}
#### Data::Printer ####
sub _data_printer {
my ($self, $ddp) = @_;
my @data = (
[ Type => $ddp->maybe_colorize( $self->Type, 'class' ), ],
[ Dims => sprintf "%s %s %s",
$ddp->maybe_colorize('[', 'brackets'),
join(" ",
map $ddp->maybe_colorize( $self->Dim($_), 'number' ),
0..$self->NumDims-1),
$ddp->maybe_colorize(']', 'brackets'),
],
[ NumDims => $ddp->maybe_colorize( $self->NumDims, 'number' ), ],
( run in 0.485 second using v1.01-cache-2.11-cpan-96521ef73a4 )