AI-TensorFlow-Libtensorflow

 view release on metacpan or  search on metacpan

LICENSE  view on Meta::CPAN

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes

META.json  view on Meta::CPAN

            "aliased" : "0",
            "lib" : "0",
            "perl" : "5.014"
         }
      }
   },
   "release_status" : "stable",
   "resources" : {
      "homepage" : "https://github.com/EntropyOrg/perl-AI-TensorFlow-Libtensorflow",
      "repository" : {
         "type" : "git",
         "url" : "https://github.com/EntropyOrg/perl-AI-TensorFlow-Libtensorflow.git",
         "web" : "https://github.com/EntropyOrg/perl-AI-TensorFlow-Libtensorflow"
      }
   },
   "version" : "0.0.7",
   "x_generated_by_perl" : "v5.26.1",
   "x_serialization_backend" : "Cpanel::JSON::XS version 4.37",
   "x_spdx_expression" : "Apache-2.0"
}

lib/AI/TensorFlow/Libtensorflow/Buffer.pm  view on Meta::CPAN

$AI::TensorFlow::Libtensorflow::Buffer::VERSION = '0.0.7';
use strict;
use warnings;
use namespace::autoclean;
use AI::TensorFlow::Libtensorflow::Lib qw(arg);

my $ffi = AI::TensorFlow::Libtensorflow::Lib->ffi;
$ffi->mangler(AI::TensorFlow::Libtensorflow::Lib->mangler_default);
use FFI::C;
FFI::C->ffi($ffi);
$ffi->load_custom_type('AI::TensorFlow::Libtensorflow::Lib::FFIType::TFPtrSizeScalarRef'
	=> 'tf_buffer_buffer'
);

use FFI::Platypus::Buffer;
use FFI::Platypus::Memory;





lib/AI/TensorFlow/Libtensorflow/DataType.pm  view on Meta::CPAN

package AI::TensorFlow::Libtensorflow::DataType;
# ABSTRACT: Datatype enum
$AI::TensorFlow::Libtensorflow::DataType::VERSION = '0.0.7';
use strict;
use warnings;
use AI::TensorFlow::Libtensorflow::Lib;
use Const::Exporter;

use Devel::StrictMode;
use Types::Common qw(Int Str);

use namespace::autoclean;

# enum TF_DataType
# From <tensorflow/c/tf_datatype.h>
my %_ENUM_DTYPE = (
	FLOAT      =>  1,
	DOUBLE     =>  2,
	INT32      =>  3, #// Int32 tensors are always in 'host' memory.
	UINT8      =>  4,
	INT16      =>  5,
	INT8       =>  6,
	STRING     =>  7,
	COMPLEX64  =>  8, #// Single-precision complex
	# NOTE Stubbing out this duplicate so that no new code uses this.

lib/AI/TensorFlow/Libtensorflow/DataType.pm  view on Meta::CPAN

	UINT32     => 22,
	UINT64     => 23,
);
my %_REV_ENUM_DTYPE = reverse %_ENUM_DTYPE;
if( STRICT ) { # ASSERT
	die "Duplicate values for \%_ENUM_DTYPE" unless keys %_ENUM_DTYPE == keys %_REV_ENUM_DTYPE
}

my %_DTYPES;
Const::Exporter->import(
	dtypes => [
		do {
			%_DTYPES = map {
				$_ => bless \do {
					my $value = $_ENUM_DTYPE{$_};
				}, __PACKAGE__;
			} keys %_ENUM_DTYPE;
		},
		'@DTYPES' => [ sort { $$a <=> $$b } values %_DTYPES ],
	]
);
use namespace::autoclean;

my $ffi = AI::TensorFlow::Libtensorflow::Lib->ffi;
$ffi->mangler(AI::TensorFlow::Libtensorflow::Lib->mangler_for_object('DataType'));

$ffi->type('object(AI::TensorFlow::Libtensorflow::DataType,int)', 'TF_DataType');

$ffi->attach( 'Size' => ['TF_DataType'] => 'size_t' );


use overload
	'==' => '_op_num_equals',
	'eq'  => '_op_eq',
	'""'  => '_op_stringify';

sub _op_num_equals {

lib/AI/TensorFlow/Libtensorflow/DataType.pm  view on Meta::CPAN

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

AI::TensorFlow::Libtensorflow::DataType - Datatype enum

=head1 SYNOPSIS

  use AI::TensorFlow::Libtensorflow::DataType qw(FLOAT @DTYPES);
  use List::Util qw(max);

  my $dtype = FLOAT;
  is FLOAT->Size, 4, 'FLOAT is 4 bytes large';
  is max(map { $_->Size } @DTYPES), 16,
    'Largest type has sizeof() == 16 bytes';

=head1 DESCRIPTION

Enum representing native data types used inside of containers such as
L<TFTensor|AI::TensorFlow::Libtensorflow::Lib::Types/TFTensor>.

=head1 CONSTANTS

=head2 STRING

String.

=head2 BOOL

lib/AI/TensorFlow/Libtensorflow/DataType.pm  view on Meta::CPAN

Handle to a mutable resource.

=head2 VARIANT

Variant.

=head1 METHODS

=head2 Size

  my $size = $dtype->Size();

B<Returns>

=over 4

=item size_t

The number of bytes used for the DataType C<$dtype>. Returns C<0> for variable
length types such as C<STRING> or for invalid types.

=back

B<C API>: L<< C<TF_DataTypeSize>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_DataTypeSize >>

=head1 OPERATORS

=head2 C<< == >>

Numeric equality of the underlying enum integer value.

  use AI::TensorFlow::Libtensorflow::DataType qw(FLOAT);
  cmp_ok FLOAT, '==', FLOAT, 'Compare FLOAT objects numerically';
  cmp_ok FLOAT, '==', 1    , 'FLOAT enumeration is internally 1';

=head2 C<< eq >>

Compare string equality against type name.

  use AI::TensorFlow::Libtensorflow::DataType qw(FLOAT);
  cmp_ok FLOAT, 'eq', 'FLOAT', 'Compare FLOAT object to string';

=head2 C<< "" >>

Stringification to the name of the enumerated type name (e.g., FLOAT, DOUBLE).

  use AI::TensorFlow::Libtensorflow::DataType qw(DOUBLE);
  is "@{[ DOUBLE ]}", 'DOUBLE', 'Stringifies';

=head1 AUTHOR

Zakariyya Mughal <zmughal@cpan.org>

=head1 COPYRIGHT AND LICENSE

lib/AI/TensorFlow/Libtensorflow/DeviceList.pm  view on Meta::CPAN

	Incarnation => 'uint64_t',
);
for my $method (keys %methods) {
	$ffi->attach( [ "DeviceList${method}" => $method ] => [
		arg TF_DeviceList => 'list',
		arg int => 'index',
		arg TF_Status => 'status'
	] => $methods{$method} );
}

### From tensorflow/core/framework/types.cc
my %DEVICE_TYPES = (
	DEFAULT => "DEFAULT",
	CPU => "CPU",
	GPU => "GPU",
	TPU => "TPU",
	TPU_SYSTEM => "TPU_SYSTEM",
);

1;

lib/AI/TensorFlow/Libtensorflow/ImportGraphDefResults.pm  view on Meta::CPAN

my $ffi = AI::TensorFlow::Libtensorflow::Lib->ffi;
$ffi->mangler(AI::TensorFlow::Libtensorflow::Lib->mangler_default);

$ffi->attach( [ 'DeleteImportGraphDefResults' => 'DESTROY' ] => [
	arg TF_ImportGraphDefResults => 'results',
] => 'void' );

$ffi->attach( [ 'ImportGraphDefResultsReturnOutputs' => 'ReturnOutputs' ] => [
	arg TF_ImportGraphDefResults => 'results',
	arg 'int*' => 'num_outputs',
	arg 'opaque*' => { id => 'outputs', type => 'TF_Output_struct_array*' },
] => 'void' => sub {
	my ($xs, $results) = @_;
	my $num_outputs;
	my $outputs_array = undef;
	$xs->($results, \$num_outputs, \$outputs_array);
	return [] if $num_outputs == 0;

	my $sizeof_output = $ffi->sizeof('TF_Output');
	window(my $outputs_packed, $outputs_array, $sizeof_output * $num_outputs );
	# due to unpack, these are copies (no longer owned by $results)
	my @outputs = map bless(\$_, "AI::TensorFlow::Libtensorflow::Output"),
		unpack "(a${sizeof_output})*", $outputs_packed;
	return \@outputs;
});

$ffi->attach( [ 'ImportGraphDefResultsReturnOperations' => 'ReturnOperations' ] => [
	arg TF_ImportGraphDefResults => 'results',
	arg 'int*' => 'num_opers',
	arg 'opaque*' => { id => 'opers', type => 'TF_Operation_array*' },
] => 'void' => sub {
	my ($xs, $results) = @_;
	my $num_opers;
	my $opers_array = undef;
	$xs->($results, \$num_opers, \$opers_array);
	return [] if $num_opers == 0;

	my $opers_array_base_packed = buffer_to_scalar($opers_array,
		$ffi->sizeof('opaque') * $num_opers );
	my @opers = map {
		$ffi->cast('opaque', 'TF_Operation', $_ )
	} unpack "(@{[ AI::TensorFlow::Libtensorflow::Lib::_pointer_incantation ]})*", $opers_array_base_packed;
	return \@opers;
} );

$ffi->attach( [ 'ImportGraphDefResultsMissingUnusedInputMappings' => 'MissingUnusedInputMappings' ] => [
    arg TF_ImportGraphDefResults => 'results',
    arg 'int*' => 'num_missing_unused_input_mappings',
    arg 'opaque*' => { id => 'src_names', ctype => 'const char***' },
    arg 'opaque*' => { id => 'src_indexes', ctype => 'int**' },
] => 'void' => sub {
	my ($xs, $results) = @_;
	my $num_missing_unused_input_mappings;
	my $src_names;
	my $src_indexes;
	$xs->($results,
		\$num_missing_unused_input_mappings,
		\$src_names, \$src_indexes
	);
	my $src_names_str   = $ffi->cast('opaque',

lib/AI/TensorFlow/Libtensorflow/Input.pm  view on Meta::CPAN

$ffi->mangler(AI::TensorFlow::Libtensorflow::Lib->mangler_default);

record_layout_1($ffi,
	'opaque' => '_oper',   # 8 (on 64-bit)
	'int'    => '_index',  # 4

	$ffi->sizeof('opaque') == 8 ? (
		'char[4]' => ':',
	) : (),
);
$ffi->type('record(AI::TensorFlow::Libtensorflow::Input)', 'TF_Input');

sub New {
	my ($class, $args) = @_;

	my $record = $class->new({
		_oper => $ffi->cast( 'TF_Operation', 'opaque', delete $args->{oper} ),
		_index => delete $args->{index},
	});
}

lib/AI/TensorFlow/Libtensorflow/Input.pm  view on Meta::CPAN

			$record;
		} 0..$array->count-1
	]
}
sub _copy_to_other {
	my ($class, $this, $that) = @_;
       $that->_oper ($this->_oper);
       $that->_index($this->_index);
}

$ffi->load_custom_type(
	RecordArrayRef( 'InputArrayPtr',
		record_module => __PACKAGE__, with_size => 0,
	),
	=> 'TF_Input_array');
$ffi->load_custom_type(
	RecordArrayRef( 'InputArrayPtrSz',
		record_module => __PACKAGE__, with_size => 1,
	),
	=> 'TF_Input_array_sz');

1;

__END__

=pod

lib/AI/TensorFlow/Libtensorflow/Lib.pm  view on Meta::CPAN

		symbol => ['TF_Version'],
		alien => ['Alien::Libtensorflow'] );
}

sub ffi {
	state $ffi;
	$ffi ||= do {
		my $ffi = FFI::Platypus->new( api => 2 );
		$ffi->lib( __PACKAGE__->lib );

		$ffi->load_custom_type('::PointerSizeBuffer' => 'tf_config_proto_buffer');
		$ffi->load_custom_type('::PointerSizeBuffer' => 'tf_tensor_shape_proto_buffer');
		$ffi->load_custom_type('::PointerSizeBuffer' => 'tf_attr_value_proto_buffer');

		$ffi->load_custom_type('AI::TensorFlow::Libtensorflow::Lib::FFIType::TFPtrSizeScalar'
			=> 'tf_text_buffer');

		$ffi->load_custom_type( PackableMaybeArrayRef( 'DimsBuffer', pack_type => 'q' )
			=> 'tf_dims_buffer'
		);


		$ffi->type('object(AI::TensorFlow::Libtensorflow::SessionOptions)' => 'TF_SessionOptions');

		$ffi->type('object(AI::TensorFlow::Libtensorflow::Graph)' => 'TF_Graph');

		$ffi->type('object(AI::TensorFlow::Libtensorflow::OperationDescription)'
			=> 'TF_OperationDescription');

		$ffi->load_custom_type('::PtrObject', 'TF_Operation' => 'AI::TensorFlow::Libtensorflow::Operation');

		$ffi->type('opaque' => 'TF_Function');

		$ffi->type('opaque' => 'TF_FunctionOptions');

		$ffi->type('object(AI::TensorFlow::Libtensorflow::ImportGraphDefOptions)' => 'TF_ImportGraphDefOptions');

		$ffi->type('object(AI::TensorFlow::Libtensorflow::ImportGraphDefResults)' => 'TF_ImportGraphDefResults');

		$ffi->type('object(AI::TensorFlow::Libtensorflow::Session)' => 'TF_Session');

		$ffi->type('opaque' => 'TF_DeprecatedSession');

		$ffi->type('object(AI::TensorFlow::Libtensorflow::DeviceList)' => 'TF_DeviceList');

		$ffi->type('object(AI::TensorFlow::Libtensorflow::TFLibrary)' => 'TF_Library');

		$ffi->type('object(AI::TensorFlow::Libtensorflow::ApiDefMap)' => 'TF_ApiDefMap');

		$ffi->type('opaque' => 'TF_Server');



		$ffi->type('opaque' => 'TF_CheckpointReader');

		$ffi->type('opaque' => 'TF_AttrBuilder');

		$ffi->type('opaque' => 'TF_ShapeAndType');

		$ffi->type('opaque' => 'TF_ShapeAndTypeList');



		$ffi->type('opaque' => 'TF_WritableFileHandle');

		$ffi->type('opaque' => 'TF_StringStream');

		$ffi->type('opaque' => 'TF_Thread');


		$ffi->type('opaque' => 'TF_KernelBuilder');

		$ffi->type('opaque' => 'TF_OpKernelConstruction');

		$ffi->type('opaque' => 'TF_OpKernelContext');


		$ffi->type('opaque' => 'TF_VariableInputLockHolder');

		$ffi->type('opaque' => 'TF_CoordinationServiceAgent');


		$ffi->type('opaque' => 'TF_Shape');


		$ffi->type('object(AI::TensorFlow::Libtensorflow::Status)' => 'TF_Status');


		$ffi->load_custom_type('::PtrObject', 'TF_Tensor' => 'AI::TensorFlow::Libtensorflow::Tensor');


		$ffi->load_custom_type('::PtrObject', 'TF_TString' => 'AI::TensorFlow::Libtensorflow::TString');


		$ffi->type('object(AI::TensorFlow::Libtensorflow::Eager::ContextOptions)', 'TFE_ContextOptions');

		$ffi->type('object(AI::TensorFlow::Libtensorflow::Eager::Context)', 'TFE_Context');



		## Callbacks for deallocation
		# For TF_Buffer
		$ffi->type('(opaque,size_t)->void'        => 'data_deallocator_t');
		# For TF_Tensor
		$ffi->type('(opaque,size_t,opaque)->void' => 'tensor_deallocator_t');

		$ffi;
	};
}

sub mangler_default {
	my $target = (caller)[0];
	my $prefix = 'TF';
	if( $target =~ /::Eager::/ ) {
		$prefix = 'TFE';

lib/AI/TensorFlow/Libtensorflow/Lib.pm  view on Meta::CPAN

		# constructor and destructors
		return "TF_New${object_name}" if $name eq 'New';
		return "TF_Delete${object_name}" if $name eq 'Delete';

		return "TF_${object_name}$name";
	};
}

sub arg(@) {
	my $arg = AI::TensorFlow::Libtensorflow::Lib::_Arg->new(
		type => shift,
		id => shift,
	);
	return $arg, @_;
}

# from FFI::Platypus::Type::StringArray
use constant _pointer_incantation =>
  $^O eq 'MSWin32' && do { require Config; $Config::Config{archname} =~ /MSWin32-x64/ }
  ? 'Q'
  : 'L!';
use constant _size_of_pointer => FFI::Platypus->new( api => 2 )->sizeof('opaque');
use constant _pointer_buffer => "P" . _size_of_pointer;

package # hide from PAUSE
  AI::TensorFlow::Libtensorflow::Lib::_Arg {

use Class::Tiny qw(type id);

use overload
	q{""} => 'stringify',
	eq => 'eq';

sub stringify { $_[0]->type }

sub eq {
	my ($self, $other, $swap) = @_;
	"$self" eq "$other";
}

}



lib/AI/TensorFlow/Libtensorflow/Lib.pm  view on Meta::CPAN

=head1 NAME

AI::TensorFlow::Libtensorflow::Lib - Private class for AI::TensorFlow::Libtensorflow

=head2 C<tensorflow/c/c_api.h>

=head3 TF_SessionOptions

L<AI::TensorFlow::Libtensorflow::SessionOptions>

=for TF_CAPI_DEF typedef struct TF_SessionOptions TF_SessionOptions;

=head3 TF_Graph

L<AI::TensorFlow::Libtensorflow::Graph>

=for TF_CAPI_DEF typedef struct TF_Graph TF_Graph;

=head3 TF_OperationDescription

L<AI::TensorFlow::Libtensorflow::OperationDescription>

=for TF_CAPI_DEF typedef struct TF_OperationDescription TF_OperationDescription;

=head3 TF_Operation

L<AI::TensorFlow::Libtensorflow::Operation>

=for TF_CAPI_DEF typedef struct TF_Operation TF_Operation;

=head3 TF_Function

=for TF_CAPI_DEF typedef struct TF_Function TF_Function;

=head3 TF_FunctionOptions

=for TF_CAPI_DEF typedef struct TF_FunctionOptions TF_FunctionOptions;

=head3 TF_ImportGraphDefOptions

L<AI::TensorFlow::Libtensorflow::ImportGraphDefOptions>

=for TF_CAPI_DEF typedef struct TF_ImportGraphDefOptions TF_ImportGraphDefOptions;

=head3 TF_ImportGraphDefResults

L<AI::TensorFlow::Libtensorflow::ImportGraphDefResults>

=for TF_CAPI_DEF typedef struct TF_ImportGraphDefResults TF_ImportGraphDefResults;

=head3 TF_Session

L<AI::TensorFlow::Libtensorflow::Session>

=for TF_CAPI_DEF typedef struct TF_Session TF_Session;

=head3 TF_DeprecatedSession

=for TF_CAPI_DEF typedef struct TF_DeprecatedSession TF_DeprecatedSession;

=head3 TF_DeviceList

L<AI::TensorFlow::Libtensorflow::DeviceList>

=for TF_CAPI_DEF typedef struct TF_DeviceList TF_DeviceList;

=head3 TF_Library

L<AI::TensorFlow::Libtensorflow::TFLibrary>

=for TF_CAPI_DEF typedef struct TF_Library TF_Library;

=head3 TF_ApiDefMap

L<AI::TensorFlow::Libtensorflow::ApiDefMap>

=for TF_CAPI_DEF typedef struct TF_ApiDefMap TF_ApiDefMap;

=head3 TF_Server

=for TF_CAPI_DEF typedef struct TF_Server TF_Server;

=head2 C<tensorflow/c/c_api_experimental.h>

=head3 TF_CheckpointReader

=for TF_CAPI_DEF typedef struct TF_CheckpointReader TF_CheckpointReader;

=head3 TF_AttrBuilder

=for TF_CAPI_DEF typedef struct TF_AttrBuilder TF_AttrBuilder;

=head3 TF_ShapeAndType

=for TF_CAPI_DEF typedef struct TF_ShapeAndType TF_ShapeAndType;

=head3 TF_ShapeAndTypeList

=for TF_CAPI_DEF typedef struct TF_ShapeAndTypeList TF_ShapeAndTypeList;

=head2 C<tensorflow/c/env.h>

=head3 TF_WritableFileHandle

=for TF_CAPI_DEF typedef struct TF_WritableFileHandle TF_WritableFileHandle;

=head3 TF_StringStream

=for TF_CAPI_DEF typedef struct TF_StringStream TF_StringStream;

=head3 TF_Thread

=for TF_CAPI_DEF typedef struct TF_Thread TF_Thread;

=head2 C<tensorflow/c/kernels.h>

=head3 TF_KernelBuilder

=for TF_CAPI_DEF typedef struct TF_KernelBuilder TF_KernelBuilder;

=head3 TF_OpKernelConstruction

=for TF_CAPI_DEF typedef struct TF_OpKernelConstruction TF_OpKernelConstruction;

=head3 TF_OpKernelContext

=for TF_CAPI_DEF typedef struct TF_OpKernelContext TF_OpKernelContext;

=head2 C<tensorflow/c/kernels_experimental.h>

=head3 TF_VariableInputLockHolder

=for TF_CAPI_DEF typedef struct TF_VariableInputLockHolder TF_VariableInputLockHolder;

=head3 TF_CoordinationServiceAgent

=for TF_CAPI_DEF typedef struct TF_CoordinationServiceAgent TF_CoordinationServiceAgent;

=head2 C<tensorflow/c/tf_shape.h>

=head3 TF_Shape

=for TF_CAPI_DEF typedef struct TF_Shape TF_Shape;

=head2 C<tensorflow/c/tf_status.h>

=head3 TF_Status

L<AI::TensorFlow::Libtensorflow::Status>

=for TF_CAPI_DEF typedef struct TF_Status TF_Status;

=head2 C<tensorflow/c/tf_tensor.h>

=head3 TF_Tensor

L<AI::TensorFlow::Libtensorflow::Tensor>

=for TF_CAPI_DEF typedef struct TF_Tensor TF_Tensor;

=head2 C<tensorflow/tsl/platform/ctstring_internal.h>

=head3 TF_TString

L<AI::TensorFlow::Libtensorflow::TString>

=head2 C<tensorflow/c/eager/c_api.h>

=head3 TFE_ContextOptions

lib/AI/TensorFlow/Libtensorflow/Lib/FFIType/TFPtrPtrLenSizeArrayRefScalar.pm  view on Meta::CPAN

# TODO implement this

sub perl_to_native {
	...
}

sub perl_to_native_post {
	...
}

sub ffi_custom_type_api_1 {
	{
		'native_type' => 'opaque',
		'perl_to_native' => \&perl_to_native,
		'perl_to_native_post' => \&perl_to_native_post,
		argument_count => 3,
	}
}

1;

__END__

lib/AI/TensorFlow/Libtensorflow/Lib/FFIType/TFPtrSizeScalar.pm  view on Meta::CPAN

	push @stack, [ $pointer, $size ];
	arguments_set_pointer $_[1], $pointer;
	arguments_set_size_t($_[1]+1, $size);
}

sub perl_to_native_post {
	my($pointer, $size) = @{ pop @stack };
	();
}

sub ffi_custom_type_api_1
{
	{
		native_type         => 'opaque',
		perl_to_native      => \&perl_to_native,
		perl_to_native_post => \&perl_to_native_post,
		argument_count      => 2,
	}
}

1;

__END__

lib/AI/TensorFlow/Libtensorflow/Lib/FFIType/TFPtrSizeScalarRef.pm  view on Meta::CPAN

	push @stack, [ $value, $pointer, $size ];
	arguments_set_pointer( $i  , $pointer);
	arguments_set_size_t(  $i+1, $size);
}

sub perl_to_native_post {
	pop @stack;
	();
}

sub ffi_custom_type_api_1 {
	{
		'native_type' => 'opaque',
		'perl_to_native' => \&perl_to_native,
		'perl_to_native_post' => \&perl_to_native_post,
		argument_count => 2,
	}
}

1;

__END__

lib/AI/TensorFlow/Libtensorflow/Lib/FFIType/Variant/PackableArrayRef.pm  view on Meta::CPAN

use warnings;
use FFI::Platypus::Buffer qw(scalar_to_buffer buffer_to_scalar);
use FFI::Platypus::API qw( arguments_set_pointer arguments_set_sint32 );

use Package::Variant;
use Module::Runtime 'module_notional_filename';

sub make_variant {
	my ($class, $target_package, $package, %arguments) = @_;

	die "Invalid pack type, must be single character"
		unless $arguments{pack_type} =~ /^.$/;

	my @stack;

	my $perl_to_native = install perl_to_native => sub {
		my ($value, $i) = @_;
		die "Value must be an ArrayRef"
			unless defined $value && ref $value eq 'ARRAY';
		my $data = pack  $arguments{pack_type} . '*', @$value;
		my $n    = scalar @$value;
		my ($pointer, $size) = scalar_to_buffer($data);

		push @stack, [ \$data, $pointer, $size ];
		arguments_set_pointer( $i  , $pointer);
		arguments_set_sint32(  $i+1, $n);
	};

	my $perl_to_native_post = install perl_to_native_post => sub {
		my ($data_ref, $pointer, $size) = @{ pop @stack };
		$$data_ref = buffer_to_scalar($pointer, $size);
		@{$_[0]} = unpack $arguments{pack_type} . '*', $$data_ref;
		();
	};
	install ffi_custom_type_api_1 => sub {
		{
			native_type => 'opaque',
			argument_count => 2,
			perl_to_native => $perl_to_native,
			perl_to_native_post => $perl_to_native_post,
		}
	};
}

sub make_variant_package_name {
	my ($class, $package, %arguments) = @_;
	$package = "AI::TensorFlow::Libtensorflow::Lib::FFIType::TF${package}";

lib/AI/TensorFlow/Libtensorflow/Lib/FFIType/Variant/PackableMaybeArrayRef.pm  view on Meta::CPAN

use warnings;
use FFI::Platypus::Buffer qw(scalar_to_buffer buffer_to_scalar);
use FFI::Platypus::API qw( arguments_set_pointer arguments_set_sint32 );

use Package::Variant;
use Module::Runtime 'module_notional_filename';

sub make_variant {
	my ($class, $target_package, $package, %arguments) = @_;

	die "Invalid pack type, must be single character"
		unless $arguments{pack_type} =~ /^.$/;

	my @stack;

	my $perl_to_native = install perl_to_native => sub {
		my ($value, $i) = @_;
		if( defined $value ) {
			die "Value must be an ArrayRef" unless ref $value eq 'ARRAY';
			my $data = pack  $arguments{pack_type} . '*', @$value;
			my $n    = scalar @$value;
			my ($pointer, $size) = scalar_to_buffer($data);

			push @stack, [ \$data, $pointer, $size ];
			arguments_set_pointer( $i  , $pointer);
			arguments_set_sint32(  $i+1, $n);
		} else {
			my $data = undef;
			my $n    = -1;
			my ($pointer, $size) = (0, 0);
			push @stack, [ \$data, $pointer, $size ];
			arguments_set_pointer( $i  , $pointer);
			arguments_set_sint32(  $i+1, $n);
		}
	};

	my $perl_to_native_post = install perl_to_native_post => sub {
		my ($data_ref, $pointer, $size) = @{ pop @stack };
		if( ! Scalar::Util::readonly($_[0]) ) {
			$$data_ref = buffer_to_scalar($pointer, $size);
			@{$_[0]} = unpack $arguments{pack_type} . '*', $$data_ref;
		}
		();
	};
	install ffi_custom_type_api_1 => sub {
		{
			native_type => 'opaque',
			argument_count => 2,
			perl_to_native => $perl_to_native,
			perl_to_native_post => $perl_to_native_post,
		}
	};
}

sub make_variant_package_name {
	my ($class, $package, %arguments) = @_;
	$package = "AI::TensorFlow::Libtensorflow::Lib::FFIType::TF${package}";

lib/AI/TensorFlow/Libtensorflow/Lib/FFIType/Variant/RecordArrayRef.pm  view on Meta::CPAN


	my $perl_to_native_post = install perl_to_native_post => sub {
		my($data_ref, $n, $pointer, $size, $sizeof) = @{ pop @stack };
		$$data_ref = buffer_to_scalar($pointer, $size);
		@{$_[0]} = map {
			bless \$_, $record_module
		} unpack  "(a${sizeof})*", $$data_ref;
		();
	};

	install ffi_custom_type_api_1 => sub {
		{
			native_type => 'opaque',
			argument_count => ($with_size ? 2 : 1),
			perl_to_native => $perl_to_native,
			perl_to_native_post => $perl_to_native_post,
		}
	};
}

sub make_variant_package_name {
	my ($class, $package, %arguments) = @_;
	$package = "AI::TensorFlow::Libtensorflow::Lib::FFIType::TF${package}";

lib/AI/TensorFlow/Libtensorflow/Lib/Types.pm  view on Meta::CPAN

	-declare => [qw(
		TFTensor
		TFGraph
		TFDataType

		Dims
	)];
use Type::Utils -all;
use Types::Standard qw(ArrayRef Int Tuple InstanceOf);

class_type TFTensor => { class => 'AI::TensorFlow::Libtensorflow::Tensor' };

class_type TFGraph => { class => 'AI::TensorFlow::Libtensorflow::Graph' };

class_type TFDataType => { class => 'AI::TensorFlow::Libtensorflow::DataType' };

class_type TFSession => { class => 'AI::TensorFlow::Libtensorflow::Session' };

class_type TFSessionOptions => { class => 'AI::TensorFlow::Libtensorflow::SessionOptions' };

class_type TFStatus => { class => 'AI::TensorFlow::Libtensorflow::Status' };

class_type TFBuffer => { class => 'AI::TensorFlow::Libtensorflow::Buffer' };

class_type TFOperation => { class => 'AI::TensorFlow::Libtensorflow::Operation' };


declare Dims => as ArrayRef[Int];

class_type TFOutput => { class => 'AI::TensorFlow::Libtensorflow::Output' };

declare_coercion "TFOutputFromTuple",
	to_type 'TFOutput',
	from Tuple[InstanceOf['AI::TensorFlow::Libtensorflow::Operation'],Int],
	q {
		AI::TensorFlow::Libtensorflow::Output->New({
			oper  => $_->[0],
			index => $_->[1],
		});
	};

class_type TFInput => { class => 'AI::TensorFlow::Libtensorflow::Input' };

declare_coercion "TFInputFromTuple",
	to_type 'TFInput',
	from Tuple[InstanceOf['AI::TensorFlow::Libtensorflow::Operation'],Int],
	q {
		AI::TensorFlow::Libtensorflow::Input->New({
			oper  => $_->[0],
			index => $_->[1],
		});
	};

1;

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

  
  The lock for `graph` must be held when calling this function.
  
  Unless implementing advanced behavior, like custom gradient functions, you
  most likely need to call `TF_NewOperation` instead.

=back

  /* From <tensorflow/c/c_api.h> */
  TF_CAPI_EXPORT extern TF_OperationDescription* TF_NewOperationLocked(
      TF_Graph* graph, const char* op_type, const char* oper_name);

=head2 TF_NewOperation

=over 2

  Operation will only be added to *graph when TF_FinishOperation() is
  called (assuming TF_FinishOperation() does not return an error).
  *graph must not be deleted until after TF_FinishOperation() is
  called.

=back

  /* From <tensorflow/c/c_api.h> */
  TF_CAPI_EXPORT extern TF_OperationDescription* TF_NewOperation(
      TF_Graph* graph, const char* op_type, const char* oper_name);

=head2 TF_SetDevice

=over 2

  Specify the device for `desc`.  Defaults to empty, meaning unconstrained.

=back

  /* From <tensorflow/c/c_api.h> */

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

  `body_graph` starting from the inputs, and store the final outputs in
  `cond_output` and `body_outputs`.
  
  If `status` is OK, the caller must call either TF_FinishWhile or
  TF_AbortWhile on the returned TF_WhileParams. If `status` isn't OK, the
  returned TF_WhileParams is not valid, and the caller should not call
  TF_FinishWhile() or TF_AbortWhile().
  
  Missing functionality (TODO):
  - Gradients
  - Reference-type inputs
  - Directly referencing external tensors from the cond/body graphs (this is
    possible in the Python API)

=back

  /* From <tensorflow/c/c_api.h> */
  TF_CAPI_EXPORT extern TF_WhileParams TF_NewWhile(TF_Graph* g, TF_Output* inputs,
                                                   int ninputs,
                                                   TF_Status* status);

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

   description - optional human-readable description of this function.
   status - Set to OK on success and an appropriate error on failure.
  
  Note that when the same TF_Output is listed as both an input and an output,
  the corresponding function's output will equal to this input,
  instead of the original node's output.
  
  Callers must also satisfy the following constraints:
  - `inputs` cannot refer to TF_Outputs within a control flow context. For
    example, one cannot use the output of "switch" node as input.
  - `inputs` and `outputs` cannot have reference types. Reference types are
    not exposed through C API and are being replaced with Resources. We support
    reference types inside function's body to support legacy code. Do not
    use them in new code.
  - Every node in the function's body must have all of its inputs (including
    control inputs). In other words, for every node in the body, each input
    must be either listed in `inputs` or must come from another node in
    the body. In particular, it is an error to have a control edge going from
    a node outside of the body into a node in the body. This applies to control
    edges going from nodes referenced in `inputs` to nodes in the body when
    the former nodes are not in the body (automatically skipped or not
    included in explicitly specified body).
  

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN


  /* From <tensorflow/c/c_api.h> */
  TF_CAPI_EXPORT extern const char* TF_DeviceListName(const TF_DeviceList* list,
                                                      int index,
                                                      TF_Status* status);

=head2 TF_DeviceListType

=over 2

  Retrieves the type of the device at the given index.
  
  The caller must not modify or delete the string. It will be deallocated upon
  a call to TF_DeleteDeviceList.
  
  If index is out of bounds, an error code will be set in the status object,
  and a null pointer will be returned.

=back

  /* From <tensorflow/c/c_api.h> */

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN


=back

  /* From <tensorflow/c/tf_tensor.h> */
  TF_CAPI_EXPORT extern void TF_DeleteTensor(TF_Tensor*);

=head2 TF_TensorType

=over 2

  Return the type of a tensor element.

=back

  /* From <tensorflow/c/tf_tensor.h> */
  TF_CAPI_EXPORT extern TF_DataType TF_TensorType(const TF_Tensor*);

=head2 TF_SetShape

=over 2

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

=back

  /* From <tensorflow/c/tf_tensor.h> */
  TF_CAPI_EXPORT extern int64_t TF_TensorElementCount(const TF_Tensor* tensor);

=head2 TF_TensorBitcastFrom

=over 2

  Copy the internal data representation of `from` to `to`. `new_dims` and
  `num_new_dims` specify the new shape of the `to` tensor, `type` specifies its
  data type. On success, *status is set to TF_OK and the two tensors share the
  same data buffer.
  
  This call requires that the `from` tensor and the given type and shape (dims
  and num_dims) are "compatible" (i.e. they occupy the same number of bytes).
  Specifically, given from_type_size = TF_DataTypeSize(TF_TensorType(from)):
  
  ShapeElementCount(dims, num_dims) * TF_DataTypeSize(type)
  
  must equal
  
  TF_TensorElementCount(from) * from_type_size
  
  where TF_ShapeElementCount would be the number of elements in a tensor with
  the given shape.
  
  In addition, this function requires:
    * TF_DataTypeSize(TF_TensorType(from)) != 0
    * TF_DataTypeSize(type) != 0
  
  If any of the requirements are not met, *status is set to
  TF_INVALID_ARGUMENT.

=back

  /* From <tensorflow/c/tf_tensor.h> */
  TF_CAPI_EXPORT extern void TF_TensorBitcastFrom(const TF_Tensor* from,
                                                  TF_DataType type, TF_Tensor* to,
                                                  const int64_t* new_dims,
                                                  int num_new_dims,
                                                  TF_Status* status);

=head2 TF_TensorIsAligned

=over 2

  Returns bool iff this tensor is aligned.

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN


=back

  /* From <tensorflow/c/tf_tstring.h> */
  TF_CAPI_EXPORT extern void TF_StringDealloc(TF_TString *tstr);

=head2 TF_DataTypeSize

=over 2

  TF_DataTypeSize returns the sizeof() for the underlying type corresponding
  to the given TF_DataType enum value. Returns 0 for variable length types
  (eg. TF_STRING) or on failure.

=back

  /* From <tensorflow/c/tf_datatype.h> */
  TF_CAPI_EXPORT extern size_t TF_DataTypeSize(TF_DataType dt);

=head2 TF_NewOpDefinitionBuilder

=over 2

  Returns a newly allocated op definition builder for the given op name. The
  returned builder may be customized with the `TF_OpDefinitionBuilder...`
  functions and then registered with TensorFlow with TF_RegisterOpDefinition.
  

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN


  /* From <tensorflow/c/ops.h> */
  TF_CAPI_EXPORT extern void TF_DeleteOpDefinitionBuilder(
      TF_OpDefinitionBuilder* builder);

=head2 TF_OpDefinitionBuilderAddAttr

=over 2

  Adds an attr to the given TF_OpDefinitionBuilder. The spec has
  format "<name>:<type>" or "<name>:<type>=<default>"
  where <name> matches regexp [a-zA-Z][a-zA-Z0-9_]*.
  By convention, names containing only capital letters are reserved for
  attributes whose values can be inferred by the operator implementation if not
  supplied by the user. If the attribute name contains characters other than
  capital letters, the operator expects the user to provide the attribute value
  at operation runtime.
  
  <type> can be:
    "string", "int", "float", "bool", "type", "shape", or "tensor"
    "numbertype", "realnumbertype", "quantizedtype"
        (meaning "type" with a restriction on valid values)
    "{int32,int64}" or {realnumbertype,quantizedtype,string}"
        (meaning "type" with a restriction containing unions of value types)
    "{\"foo\", \"bar\n baz\"}", or "{'foo', 'bar\n baz'}"
        (meaning "string" with a restriction on valid values)
    "list(string)", ..., "list(tensor)", "list(numbertype)", ...
        (meaning lists of the above types)
    "int >= 2" (meaning "int" with a restriction on valid values)
    "list(string) >= 2", "list(int) >= 2"
        (meaning "list(string)" / "list(int)" with length at least 2)
  <default>, if included, should use the Proto text format
  of <type>.  For lists use [a, b, c] format.
  
  Note that any attr specifying the length of an input or output will
  get a default minimum of 1 unless the >= # syntax is used.

=back

  /* From <tensorflow/c/ops.h> */
  TF_CAPI_EXPORT extern void TF_OpDefinitionBuilderAddAttr(
      TF_OpDefinitionBuilder* builder, const char* attr_spec);

=head2 TF_OpDefinitionBuilderAddInput

=over 2

  Adds an input to this TF_OpDefinitionBuilder.
  The spec has form "<name>:<type-expr>" or "<name>:Ref(<type-expr>)"
  where <name> matches regexp [a-z][a-z0-9_]* and <type-expr> can be:
  * For a single tensor: <type>
  * For a sequence of tensors with the same type: <number>*<type>
  * For a sequence of tensors with different types: <type-list>
  Where:
    <type> is either one of "float", "int32", "string", ...
           or the name of an attr (see TF_OpDefinitionBuilderAddAttr)
           with type "type".
    <number> is the name of an attr with type "int".
    <type-list> is the name of an attr with type "list(type)".

=back

  /* From <tensorflow/c/ops.h> */
  TF_CAPI_EXPORT extern void TF_OpDefinitionBuilderAddInput(
      TF_OpDefinitionBuilder* builder, const char* input_spec);

=head2 TF_OpDefinitionBuilderAddOutput

=over 2

  Adds an output to this TF_OpDefinitionBuilder.
  The spec has form "<name>:<type-expr>" or "<name>:Ref(<type-expr>)"
  where <name> matches regexp [a-z][a-z0-9_]* and <type-expr> can be:
  * For a single tensor: <type>
  * For a sequence of tensors with the same type: <number>*<type>
  * For a sequence of tensors with different types: <type-list>
  Where:
    <type> is either one of "float", "int32", "string", ...
           or the name of an attr (see TF_OpDefinitionBuilderAddAttr)
           with type "type".
    <number> is the name of an attr with type "int".
    <type-list> is the name of an attr with type "list(type)".

=back

  /* From <tensorflow/c/ops.h> */
  TF_CAPI_EXPORT extern void TF_OpDefinitionBuilderAddOutput(
      TF_OpDefinitionBuilder* builder, const char* output_spec);

=head2 TF_OpDefinitionBuilderSetIsCommutative

=over 2

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

  TF_CAPI_EXPORT extern void TF_OpDefinitionBuilderSetIsCommutative(
      TF_OpDefinitionBuilder* builder, bool is_commutative);

=head2 TF_OpDefinitionBuilderSetIsAggregate

=over 2

  Sets the is_aggregate property of the builder to the given value.
  
  If is_aggregate is true, then the operation produced by this builder accepts
  N >= 2 inputs and produces 1 output all of the same type. Should be
  associative and commutative, and produce output with the same shape as the
  input. The optimizer may replace an aggregate op taking input from multiple
  devices with a tree of aggregate ops that aggregate locally within each
  device (and possibly within groups of nearby devices) before communicating.

=back

  /* From <tensorflow/c/ops.h> */
  TF_CAPI_EXPORT extern void TF_OpDefinitionBuilderSetIsAggregate(
      TF_OpDefinitionBuilder* builder, bool is_aggregate);

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

  and deleting entries as they are encountered.
  
  If dirname itself is not readable or does not exist, *undeleted_dir_count is
  set to 1, *undeleted_file_count is set to 0 and an appropriate status (e.g.
  TF_NOT_FOUND) is returned.
  
  If dirname and all its descendants were successfully deleted, TF_OK is
  returned and both error counters are set to zero.
  
  Otherwise, while traversing the tree, undeleted_file_count and
  undeleted_dir_count are updated if an entry of the corresponding type could
  not be deleted. The returned error status represents the reason that any one
  of these entries could not be deleted.
  
  Typical status codes:
   * TF_OK - dirname exists and we were able to delete everything underneath
   * TF_NOT_FOUND - dirname doesn't exist
   * TF_PERMISSION_DENIED - dirname or some descendant is not writable
   * TF_UNIMPLEMENTED - some underlying functions (like Delete) are not
     implemented

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

  TF_CAPI_EXPORT extern TF_KernelBuilder* TF_NewKernelBuilder(
      const char* op_name, const char* device_name,
      void* (*create_func)(TF_OpKernelConstruction*),
      void (*compute_func)(void*, TF_OpKernelContext*),
      void (*delete_func)(void*));

=head2 TF_KernelBuilder_TypeConstraint

=over 2

  Specifies that this kernel's attribute only supports the given type.

=back

  /* From <tensorflow/c/kernels.h> */
  TF_CAPI_EXPORT extern void TF_KernelBuilder_TypeConstraint(
      TF_KernelBuilder* kernel_builder, const char* attr_name,
      const TF_DataType type, TF_Status* status);

=head2 TF_KernelBuilder_HostMemory

=over 2

  Specify that this kernel requires/provides an input/output arg
  in host memory (instead of the default, device memory).

=back

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

=back

  /* From <tensorflow/c/kernels.h> */
  TF_CAPI_EXPORT extern void TF_OpKernelContext_Failure(TF_OpKernelContext* ctx,
                                                        TF_Status* status);

=head2 TF_ExpectedOutputDataType

=over 2

  Returns the expected output data type of the ith output. If i < 0 or
  i >= TF_NumOutputs(ctx), the program aborts.

=back

  /* From <tensorflow/c/kernels.h> */
  TF_CAPI_EXPORT extern TF_DataType TF_ExpectedOutputDataType(
      TF_OpKernelContext* ctx, int i);

=head2 TF_IsHostMemoryInput

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

  TF_CAPI_EXPORT extern TF_StringView TF_GetOpKernelRequestedInput(
      TF_OpKernelContext* ctx, size_t index);

=head2 TF_OpKernelConstruction_GetAttrSize

=over 2

  Get the list_size and total_size of the attribute `attr_name` of `oper`.
  list_size - the length of the list.
  total_size - total size of the list.
    (1) If attr_type == TF_ATTR_STRING
        then total_size is the cumulative byte size
        of all the strings in the list.
    (3) If attr_type == TF_ATTR_SHAPE
        then total_size is the number of dimensions
        of the shape valued attribute, or -1
        if its rank is unknown.
    (4) If attr_type == TF_ATTR_SHAPE
        then total_size is the cumulative number
        of dimensions of all shapes in the list.
    (5) Otherwise, total_size is undefined.

=back

  /* From <tensorflow/c/kernels.h> */
  TF_CAPI_EXPORT extern void TF_OpKernelConstruction_GetAttrSize(
      TF_OpKernelConstruction* ctx, const char* attr_name, int32_t* list_size,
      int32_t* total_size, TF_Status* status);

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

  Allocates Tensor for output at given index. Caller takes ownership of
  returned TF_Tensor and should deallocate it using TF_DeleteTensor(tensor).
  
  This function should be used to allocate outputs inside kernel
  compute function.

=back

  /* From <tensorflow/c/kernels.h> */
  TF_CAPI_EXPORT TF_Tensor* TF_AllocateOutput(TF_OpKernelContext* context,
                                              int index, TF_DataType dtype,
                                              const int64_t* dims, int num_dims,
                                              size_t len, TF_Status* status);

=head2 TF_ForwardInputOrAllocateOutput

=over 2

  Tries to forward one of the inputs given in input_indices to
  output[output_index]. If none of the given inputs can be forwarded, calls
  allocate_output() to allocate a new output buffer. The index of the

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

  TF_CAPI_EXPORT TF_Tensor* TF_ForwardInputOrAllocateOutput(
      TF_OpKernelContext* context, const int* candidate_input_indices,
      int num_candidate_input_indices, int output_index,
      const int64_t* output_dims, int output_num_dims, int* forwarded_input,
      TF_Status* status);

=head2 TF_AllocateTemp

=over 2

  Allocates a temporary Tensor of the specified type and shape. The
  Tensor must not be used after kernel construction is
  complete.
  
  num_dims must equal the size of array dims

=back

  /* From <tensorflow/c/kernels.h> */
  TF_CAPI_EXPORT extern TF_Tensor* TF_AllocateTemp(
      TF_OpKernelContext* context, TF_DataType dtype, const int64_t* dims,
      int num_dims, TF_AllocatorAttributes* alloc_attrs, TF_Status* status);

=head2 TF_AssignVariable

=over 2

  Expose higher level Assignment operation for Pluggable vendors to implement
  in the plugin for Training. The API takes in the context with indices for
  the input and value tensors. It also accepts the copy callback provided by
  pluggable vendor to do the copying of the tensors. The caller takes ownership

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN


  /* From <tensorflow/c/kernels_experimental.h> */
  TF_CAPI_EXPORT extern bool TF_IsRefInput(TF_OpKernelContext* ctx, int i,
                                           TF_Status* status);

=head2 TF_AddNVariant

=over 2

  Expose higher level AddN operation for Pluggable vendors to implement
  in the plugin for Variant data types. The API takes in the context and a
  callback provided by pluggable vendor to do a Binary Add operation on the
  tensors unwrapped from the Variant tensors. The caller takes ownership of the
  `a`, `b` and `out` tensors and is responsible for freeing them with
  TF_DeleteTensor.

=back

  /* From <tensorflow/c/kernels_experimental.h> */
  TF_CAPI_EXPORT extern void TF_AddNVariant(
      TF_OpKernelContext* ctx,
      void (*binary_add_func)(TF_OpKernelContext* ctx, TF_Tensor* a, TF_Tensor* b,
                              TF_Tensor* out),
      TF_Status* status);

=head2 TF_ZerosLikeVariant

=over 2

  Expose higher level ZerosLike operation for Pluggable vendors to implement
  in the plugin for Variant data types. The API takes in the context and a
  callback provided by pluggable vendor to do a ZerosLike operation on the
  tensors unwrapped from the Variant tensors. The caller takes ownership of the
  `input` and `out` tensors and is responsible for freeing them with
  TF_DeleteTensor.

=back

  /* From <tensorflow/c/kernels_experimental.h> */
  TF_CAPI_EXPORT extern void TF_ZerosLikeVariant(
      TF_OpKernelContext* ctx,

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

  /* From <tensorflow/c/eager/c_api.h> */
  TF_CAPI_EXPORT extern TF_AttrType TFE_OpGetAttrType(TFE_Op* op,
                                                      const char* attr_name,
                                                      unsigned char* is_list,
                                                      TF_Status* status);

=head2 TFE_OpNameGetAttrType

=over 2

  Get an attribute type given an op name; a fusion of TFE_NewOp and
  TFE_OpGetAttrType for use from Python without the overhead of the individual
  calls and memory management of TFE_Op.

=back

  /* From <tensorflow/c/eager/c_api.h> */
  TF_CAPI_EXPORT extern TF_AttrType TFE_OpNameGetAttrType(
      TFE_Context* ctx, const char* op_or_function_name, const char* attr_name,
      unsigned char* is_list, TF_Status* status);

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN


=head2 TFE_TensorHandleDevicePointer

=over 2

  This function will block till the operation that produces `h` has
  completed. This is only valid on local TFE_TensorHandles. The pointer
  returned will be on the device in which the TFE_TensorHandle resides (so e.g.
  for a GPU tensor this will return a pointer to GPU memory). The pointer is
  only guaranteed to be valid until TFE_DeleteTensorHandle is called on this
  TensorHandle. Only supports POD data types.

=back

  /* From <tensorflow/c/eager/c_api_experimental.h> */
  TF_CAPI_EXPORT extern void* TFE_TensorHandleDevicePointer(TFE_TensorHandle*,
                                                            TF_Status*);

=head2 TFE_TensorHandleDeviceMemorySize

=over 2

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

  Registers a custom device for use with eager execution.
  
  Eager operations may be placed on this device, e.g.  `with
  tf.device("CUSTOM"):` from Python if `device_name` for this call is
  "/job:localhost/replica:0/task:0/device:CUSTOM:0".
  
  The custom device defines copy operations for moving TensorHandles on and
  off, and an execution operation for named operations. Often execution will
  simply wrap op execution on one or more physical devices.
  
  device_info is an opaque caller-defined type stored with the custom device
  which is passed to the functions referenced in the TFE_CustomDevice struct
  `device` (execute, delete_device, etc.). It can for example contain the
  names of wrapped devices.
  
  There are currently no graph semantics implemented for registered custom
  devices, so executing tf.functions which contain operations placed on the
  custom devices will fail.
  
  `device_name` must not name an existing physical or custom device. It must
  follow the format:
  
     /job:<name>/replica:<replica>/task:<task>/device:<type>:<device_num>
  
  If the device is successfully registered, `status` is set to TF_OK. Otherwise
  the device is not usable. In case of a bad status, `device.delete_device` is
  still called on `device_info` (i.e. the caller does not retain ownership).
  
  This API is highly experimental, and in particular is expected to change when
  it starts supporting operations with attributes and when tf.function support
  is added.

=back

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN


  Allocate and return a new Tensor on the host.
  
  The caller must set the Tensor values by writing them to the pointer returned
  by TF_TensorData with length TF_TensorByteSize.

=back

  /* From <tensorflow/c/eager/c_api_experimental.h> */
  TF_CAPI_EXPORT extern TF_Tensor* TFE_AllocateHostTensor(TFE_Context* ctx,
                                                          TF_DataType dtype,
                                                          const int64_t* dims,
                                                          int num_dims,
                                                          TF_Status* status);

=head2 TFE_NewTensorHandleFromTensor

=over 2

  Given a Tensor, wrap it with a TensorHandle
  

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN


  /* From <tensorflow/c/eager/c_api_experimental.h> */
  TF_CAPI_EXPORT void TFE_ContextSetJitCompileRewrite(TFE_Context* ctx,
                                                      unsigned char enable,
                                                      TF_Status* status);

=head2 TFE_TensorHandleDeviceType

=over 2

  Returns the device type of the operation that produced `h`.

=back

  /* From <tensorflow/c/eager/c_api_experimental.h> */
  TF_CAPI_EXPORT extern const char* TFE_TensorHandleDeviceType(
      TFE_TensorHandle* h, TF_Status* status);

=head2 TFE_TensorHandleDeviceID

=over 2

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN


  /* From <tensorflow/c/experimental/grappler/grappler.h> */
  TF_CAPI_EXPORT extern void TF_LookUpOpDef(TF_FunctionLibraryDefinition* fn_lib,
                                            const char* name, TF_Buffer* buf,
                                            TF_Status* s);

=head2 TF_TensorSpecDataType

=over 2

  Returns the dtype associated with the TensorSpec.

=back

  /* From <tensorflow/c/experimental/saved_model/public/tensor_spec.h> */
  TF_CAPI_EXPORT extern TF_DataType TF_TensorSpecDataType(
      const TF_TensorSpec* spec);

=head2 TF_TensorSpecShape

=over 2

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

=over 2

  Returns a TFE_Op suitable for executing this function. Caller must provide
  all function inputs in `inputs`, and must not add any additional inputs on
  the returned op. (i.e. don't call TFE_OpAddInput or TFE_OpAddInputList).
  The caller is responsible for deleting the returned TFE_Op. If op
  construction fails, `status` will be non-OK and the returned pointer will be
  null.
  TODO(bmzhao): Remove this function in a subsequent change; Design + implement
  a Function Execution interface for ConcreteFunction that accepts a tagged
  union of types (tensorflow::Value). This effectively requires moving much of
  the implementation of function.py/def_function.py to C++, and exposing a
  high-level API here. A strawman for what this interface could look like:
  TF_Value* TF_ExecuteFunction(TFE_Context*, TF_ConcreteFunction*, TF_Value*
  inputs, int num_inputs, TF_Status* status);

=back

  /* From <tensorflow/c/experimental/saved_model/public/concrete_function.h> */
  TF_CAPI_EXPORT extern TFE_Op* TF_ConcreteFunctionMakeCallOp(
      TF_ConcreteFunction* func, TFE_TensorHandle** inputs, int num_inputs,

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

  TF_CAPI_EXPORT extern void TF_AttrBuilderSetTypeList(TF_AttrBuilder* builder,
                                                       const char* attr_name,
                                                       const TF_DataType* values,
                                                       int num_values);

=head2 TF_AttrBuilderCheckCanRunOnDevice

=over 2

  Checks the tensorflow::NodeDef built via the methods above to see if it can
  run on device_type.

=back

  /* From <tensorflow/c/c_api_experimental.h> */
  TF_CAPI_EXPORT extern void TF_AttrBuilderCheckCanRunOnDevice(
      TF_AttrBuilder* builder, const char* device_type, TF_Status* status);

=head2 TF_GetNumberAttrForOpListInput

=over 2

  For argument number input_index, fetch the corresponding number_attr that
  needs to be updated with the argument length of the input list.
  Returns nullptr if there is any problem like op_name is not found, or the
  argument does not support this attribute type.

=back

  /* From <tensorflow/c/c_api_experimental.h> */
  TF_CAPI_EXPORT extern const char* TF_GetNumberAttrForOpListInput(
      const char* op_name, int input_index, TF_Status* status);

=head2 TF_OpIsStateful

=over 2

  Returns 1 if the op is stateful, 0 otherwise. The return value is undefined
  if the status is not ok.

=back

  /* From <tensorflow/c/c_api_experimental.h> */
  TF_CAPI_EXPORT extern int TF_OpIsStateful(const char* op_type,
                                            TF_Status* status);

=head2 TF_InitMain

=over 2

  Platform specific initialization routine. Very few platforms actually require
  this to be called.

=back

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN


=over 2

  Fast path method that makes constructing a single scalar tensor require less
  overhead and copies.

=back

  /* From <tensorflow/c/c_api_experimental.h> */
  TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_NewTensorHandleFromScalar(
      TF_DataType data_type, void* data, size_t len, TF_Status* status);

=head2 TFE_EnableCollectiveOps

=over 2

  Specify the server_def that enables collective ops.
  This is different to the above function in that it doesn't create remote
  contexts, and remotely executing ops is not possible. It just enables
  communication for collective ops.

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

=head2 TF_ShapeAndTypeListSetUnknownShape

=over 2

=back

  /* From <tensorflow/c/c_api_experimental.h> */
  TF_CAPI_EXPORT extern void TF_ShapeAndTypeListSetUnknownShape(
      TF_ShapeAndTypeList* shape_list, int index);

=head2 TF_ShapeAndTypeListSetDtype

=over 2

=back

  /* From <tensorflow/c/c_api_experimental.h> */
  TF_CAPI_EXPORT extern void TF_ShapeAndTypeListSetDtype(
      TF_ShapeAndTypeList* shape_list, int index, TF_DataType dtype);

=head2 TF_DeleteShapeAndTypeList

=over 2

=back

  /* From <tensorflow/c/c_api_experimental.h> */
  TF_CAPI_EXPORT extern void TF_DeleteShapeAndTypeList(
      TF_ShapeAndTypeList* shape_list);

lib/AI/TensorFlow/Libtensorflow/Manual/CAPI.pod  view on Meta::CPAN

=head2 TFE_InferShapes

=over 2

  Infer shapes for the given `op`. The arguments mimic the arguments of the
  `shape_inference::InferenceContext` constructor. Note the following:
    - The inputs of the `op` are not used for shape inference. So, it is
      OK to not have the inputs properly set in `op`. See `input_tensors`
      if you want shape inference to consider the input tensors of the
      op for shape inference.
    - The types need not be set in `input_shapes` as it is not used.
    - The number of `input_tensors` should be the same as the number of items
      in `input_shapes`.
  
  The results are returned in `output_shapes` and
  `output_resource_shapes_and_types`. The caller is responsible for freeing the
  memory in these buffers by calling `TF_DeleteShapeAndTypeList`.

=back

  /* From <tensorflow/c/c_api_experimental.h> */
  TF_CAPI_EXPORT extern void TFE_InferShapes(
      TFE_Op* op, TF_ShapeAndTypeList* input_shapes, TF_Tensor** input_tensors,
      TF_ShapeAndTypeList* input_tensor_as_shapes,
      TF_ShapeAndTypeList** input_resource_shapes_and_types,
      TF_ShapeAndTypeList** output_shapes,
      TF_ShapeAndTypeList*** output_resource_shapes_and_types, TF_Status* status);

=head2 TF_ImportGraphDefOptionsSetValidateColocationConstraints

=over 2

=back

  /* From <tensorflow/c/c_api_experimental.h> */
  TF_CAPI_EXPORT extern void
  TF_ImportGraphDefOptionsSetValidateColocationConstraints(

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod  view on Meta::CPAN

            detection_classes => 1,
            detection_scores  => 2,
            num_detections    => 3,
        }
    },
);

my %outputs;

%outputs = map {
    my $put_type = $_;
    my $op = $ops{$put_type}{op};
    my $port_dict = $ops{$put_type}{dict};

   $put_type => +{
        map {
            my $dict_key = $_;
            my $index = $port_dict->{$_};
            $dict_key => AI::TensorFlow::Libtensorflow::Output->New( {
                oper => $op,
                index => $index,
            });
        } keys %$port_dict
     }
} keys %ops;

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod  view on Meta::CPAN

    my $http = HTTP::Tiny->new;
    my $response = $http->get( $uri );
    die "Could not fetch image from $uri" unless $response->{success};
    say "Downloaded $uri";

    my $img = Imager->new;
    $img->read( data => $response->{content} );

    # Create PDL ndarray from Imager data in-memory.
    my $data;
    $img->write( data => \$data, type => 'raw' )
        or die "could not write ". $img->errstr;

    die "Image does not have 3 channels, it has @{[ $img->getchannels ]} channels"
        if $img->getchannels != 3;

    # $data is packed as PDL->dims == [w,h] with RGB pixels
    my $pdl_raw = zeros(byte, $img->getchannels, $img->getwidth, $img->getheight);
    ${ $pdl_raw->get_dataref } = $data;
    $pdl_raw->upd_data;

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod  view on Meta::CPAN

C<detection_classes>: a C<tf.int> tensor of shape [N] containing detection class index from the label file.

=item -

C<detection_scores>: a C<tf.float32> tensor of shape [N] containing detection scores.

=back

=back

Note that the above documentation has two errors: both C<num_detections> and C<detection_classes> are not of type C<tf.int>, but are actually C<tf.float32>.

Now we can load the model from that folder with the tag set C<[ 'serve' ]> by using the C<LoadFromSavedModel> constructor to create a C<::Graph> and a C<::Session> for that graph.

  my $opt = AI::TensorFlow::Libtensorflow::SessionOptions->New;
  
  my $graph = AI::TensorFlow::Libtensorflow::Graph->New;
  my $session = AI::TensorFlow::Libtensorflow::Session->LoadFromSavedModel(
      $opt, undef, $model_base, \@tags, $graph, undef, $s
  );
  AssertOK($s);

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod  view on Meta::CPAN

              detection_classes => 1,
              detection_scores  => 2,
              num_detections    => 3,
          }
      },
  );
  
  my %outputs;
  
  %outputs = map {
      my $put_type = $_;
      my $op = $ops{$put_type}{op};
      my $port_dict = $ops{$put_type}{dict};
  
     $put_type => +{
          map {
              my $dict_key = $_;
              my $index = $port_dict->{$_};
              $dict_key => AI::TensorFlow::Libtensorflow::Output->New( {
                  oper => $op,
                  index => $index,
              });
          } keys %$port_dict
       }
  } keys %ops;

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubCenterNetObjDetect.pod  view on Meta::CPAN

                  width => '100%',
              })
          ),
      );
  }

=head2 Download the test image and transform it into suitable input data

We now fetch the image and prepare it to be in the needed format by using C<Imager>. Note that this model does not need the input image to be of a certain size so no resizing or padding is required.

Then we turn the C<Imager> data into a C<PDL> ndarray. Since we just need the 3 channels of the image as they are, they can be stored directly in a C<PDL> ndarray of type C<byte>.

The reason why we need to concatenate the C<PDL> ndarrays here despite the model only taking a single image at a time is to get an ndarray with four (4) dimensions with the last C<PDL> dimension of size one (1).

  sub load_image_to_pdl {
      my ($uri, $image_size) = @_;
  
      my $http = HTTP::Tiny->new;
      my $response = $http->get( $uri );
      die "Could not fetch image from $uri" unless $response->{success};
      say "Downloaded $uri";
  
      my $img = Imager->new;
      $img->read( data => $response->{content} );
  
      # Create PDL ndarray from Imager data in-memory.
      my $data;
      $img->write( data => \$data, type => 'raw' )
          or die "could not write ". $img->errstr;
  
      die "Image does not have 3 channels, it has @{[ $img->getchannels ]} channels"
          if $img->getchannels != 3;
  
      # $data is packed as PDL->dims == [w,h] with RGB pixels
      my $pdl_raw = zeros(byte, $img->getchannels, $img->getwidth, $img->getheight);
      ${ $pdl_raw->get_dataref } = $data;
      $pdl_raw->upd_data;
  

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod  view on Meta::CPAN

  );

B<STREAM (STDOUT)>:

  MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:
  
  signature_def['__saved_model_init_op']:
    The given SavedModel SignatureDef contains the following input(s):
    The given SavedModel SignatureDef contains the following output(s):
      outputs['__saved_model_init_op'] tensor_info:
          dtype: DT_INVALID
          shape: unknown_rank
          name: NoOp
    Method name is: 
  
  Concrete Functions:
B<RESULT>:

  1

It appears that it does not! What we can do is load the model using C<tensorflow> in Python and then save it to a new path. Now when we run C<saved_model_cli show> on this new model path, it shows the correct inputs and outputs.

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubEnformerGeneExprPredModel.pod  view on Meta::CPAN

  );

B<STREAM (STDOUT)>:

  MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:
  
  signature_def['__saved_model_init_op']:
    The given SavedModel SignatureDef contains the following input(s):
    The given SavedModel SignatureDef contains the following output(s):
      outputs['__saved_model_init_op'] tensor_info:
          dtype: DT_INVALID
          shape: unknown_rank
          name: NoOp
    Method name is: 
  
  signature_def['serving_default']:
    The given SavedModel SignatureDef contains the following input(s):
      inputs['args_0'] tensor_info:
          dtype: DT_FLOAT
          shape: (-1, 393216, 4)
          name: serving_default_args_0:0
    The given SavedModel SignatureDef contains the following output(s):
      outputs['human'] tensor_info:
          dtype: DT_FLOAT
          shape: (-1, 896, 5313)
          name: StatefulPartitionedCall:0
      outputs['mouse'] tensor_info:
          dtype: DT_FLOAT
          shape: (-1, 896, 1643)
          name: StatefulPartitionedCall:1
    Method name is: tensorflow/serving/predict
  
  Concrete Functions:
    Function Name: 'predict_on_batch'
      Option #1
        Callable with:
          Argument #1
            args_0: TensorSpec(shape=(None, 393216, 4), dtype=tf.float32, name='args_0')

B<RESULT>:

  1

We want to use the C<serve> tag-set and

=over

=item *

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod  view on Meta::CPAN

        src  => $inner,
    );

    $outer;
}

sub imager_scale_to {
    my ($img, $image_size) = @_;
    my $rescaled = $img->scale(
        List::Util::mesh( [qw(xpixels ypixels)], $image_size ),
        type => 'min',
        qtype => 'mixing', # 'mixing' seems to work better than 'normal'
    );
}

sub load_image_to_pdl {
    my ($uri, $image_size) = @_;

    my $http = HTTP::Tiny->new;
    my $response = $http->get( $uri );
    die "Could not fetch image from $uri" unless $response->{success};
    say "Downloaded $uri";

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod  view on Meta::CPAN


    my $padded = imager_paste_center_pad($rescaled, $image_size,
        # ARGB fits in 32-bits (uint32_t)
        channels => 4
    );

    say sprintf "Padded to [ %d x %d ]", $padded->getwidth, $padded->getheight;

    # Create PDL ndarray from Imager data in-memory.
    my $data;
    $padded->write( data => \$data, type => 'raw' )
        or die "could not write ". $padded->errstr;

    # $data is packed as PDL->dims == [w,h] with ARGB pixels
    #   $ PDL::howbig(ulong) # 4
    my $pdl_raw = zeros(ulong, $padded->getwidth, $padded->getheight);
    ${ $pdl_raw->get_dataref } = $data;
    $pdl_raw->upd_data;

    # Split uint32_t pixels into first dimension with 3 channels (R,G,B) with values 0-255.
    my @shifts = map 8*$_, 0..2;

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod  view on Meta::CPAN

  use Imager;
  
  my $s = AI::TensorFlow::Libtensorflow::Status->New;
  sub AssertOK {
      die "Status $_[0]: " . $_[0]->Message
          unless $_[0]->GetCode == AI::TensorFlow::Libtensorflow::Status::OK;
      return;
  }
  AssertOK($s);

In this notebook, we will use C<PDL> to store and manipulate the ndarray data before converting it to a C<TFTensor>. The following functions help with copying the data back and forth between the two object types.

An important thing to note about the dimensions used by TensorFlow's TFTensors when compared with PDL is that the dimension lists are reversed. Consider a binary raster image with width W and height H stored in L<row-major format|https://en.wikipedia...

This difference will be explained more concretely further in the tutorial.

Future work will provide an API for more convenient wrappers which will provide an option to either copy or share the same data (if possible).

  use PDL;
  use AI::TensorFlow::Libtensorflow::DataType qw(FLOAT);
  

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod  view on Meta::CPAN

          qw(--signature_def) => 'serving_default'
      ) == 0 or die "Could not run saved_model_cli";
  } else {
      say "Install the tensorflow Python package to get the `saved_model_cli` command.";
  }

B<STREAM (STDOUT)>:

  The given SavedModel SignatureDef contains the following input(s):
    inputs['inputs'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 224, 224, 3)
        name: serving_default_inputs:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['logits'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1001)
        name: StatefulPartitionedCall:0
  Method name is: tensorflow/serving/predict

B<RESULT>:

  1

The above C<saved_model_cli> output shows that the model input is at C<serving_default_inputs:0> which means the operation named C<serving_default_inputs> at index C<0> and the output is at C<StatefulPartitionedCall:0> which means the operation named...

It also shows the type and shape of the C<TFTensor>s for those inputs and outputs. Together this is known as a signature.

For the C<input>, we have C<(-1, 224, 224, 3)> which is a L<common input image specification for TensorFlow Hub|https://www.tensorflow.org/hub/common_signatures/images#input>. This is known as C<channels_last> (or C<NHWC>) layout where the TensorFlow...

For the C<output>, we have C<(-1, 1001)> which is C<[batch_size, num_classes]> where the elements are scores that the image received for that ImageNet class.

Now we can load the model from that folder with the tag set C<[ 'serve' ]> by using the C<LoadFromSavedModel> constructor to create a C<::Graph> and a C<::Session> for that graph.

  my $opt = AI::TensorFlow::Libtensorflow::SessionOptions->New;
  
  my $graph = AI::TensorFlow::Libtensorflow::Graph->New;

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod  view on Meta::CPAN

          src  => $inner,
      );
  
      $outer;
  }
  
  sub imager_scale_to {
      my ($img, $image_size) = @_;
      my $rescaled = $img->scale(
          List::Util::mesh( [qw(xpixels ypixels)], $image_size ),
          type => 'min',
          qtype => 'mixing', # 'mixing' seems to work better than 'normal'
      );
  }
  
  sub load_image_to_pdl {
      my ($uri, $image_size) = @_;
  
      my $http = HTTP::Tiny->new;
      my $response = $http->get( $uri );
      die "Could not fetch image from $uri" unless $response->{success};
      say "Downloaded $uri";

lib/AI/TensorFlow/Libtensorflow/Manual/Notebook/InferenceUsingTFHubMobileNetV2Model.pod  view on Meta::CPAN

  
      my $padded = imager_paste_center_pad($rescaled, $image_size,
          # ARGB fits in 32-bits (uint32_t)
          channels => 4
      );
  
      say sprintf "Padded to [ %d x %d ]", $padded->getwidth, $padded->getheight;
  
      # Create PDL ndarray from Imager data in-memory.
      my $data;
      $padded->write( data => \$data, type => 'raw' )
          or die "could not write ". $padded->errstr;
  
      # $data is packed as PDL->dims == [w,h] with ARGB pixels
      #   $ PDL::howbig(ulong) # 4
      my $pdl_raw = zeros(ulong, $padded->getwidth, $padded->getheight);
      ${ $pdl_raw->get_dataref } = $data;
      $pdl_raw->upd_data;
  
      # Split uint32_t pixels into first dimension with 3 channels (R,G,B) with values 0-255.
      my @shifts = map 8*$_, 0..2;

lib/AI/TensorFlow/Libtensorflow/Manual/Quickstart.pod  view on Meta::CPAN

=over 4

=item L<AI::TensorFlow::Libtensorflow::Status>

Used for error-handling. Many methods take this as the final argument which is
then checked after the method call to ensure that it completed successfully.

=item L<AI::TensorFlow::Libtensorflow::Tensor>, L<AI::TensorFlow::Libtensorflow::DataType>

A C<TFTensor> is a multi-dimensional data structure that stores the data for inputs and outputs.
Each element has the same data type
which is defined by L<AI::TensorFlow::Libtensorflow::DataType>
thus a C<TFTensor> is considered to be "homogeneous data structure".
See L<Introduction to Tensors|https://www.tensorflow.org/guide/tensor> for more.

=item L<AI::TensorFlow::Libtensorflow::OperationDescription>, L<AI::TensorFlow::Libtensorflow::Operation>

An operation is a function that has inputs and outputs. It has a user-defined
name (such as C<MyAdder>) and library-defined type (such as C<AddN>).
L<AI::TensorFlow::Libtensorflow::OperationDescription> is used to build an
operation that will be added to a graph of other operations where those other
operations can set the operation's inputs and get the operation's outputs.
These inputs and outputs have types and dimension specifications, so that the
operations only accept and emit certain C<TFTensor>s.

=item L<AI::TensorFlow::Libtensorflow::Graph>

A set of operations with inputs and outputs linked together. This computation
can be serialized along with parameters as part of
a L<SavedModel|https://www.tensorflow.org/guide/saved_model>.

=item L<AI::TensorFlow::Libtensorflow::Session>, L<AI::TensorFlow::Libtensorflow::SessionOptions>

A session drives the execution of a L<AI::TensorFlow::Libtensorflow::Graph>.
Specifics of how the session executes can be set via L<AI::TensorFlow::Libtensorflow::SessionOptions>.

=back

=head1 TUTORIALS

The object types in L</OBJECT TYPES> are used in the following tutorials:

=over 4

=item L<InferenceUsingTFHubMobileNetV2Model|AI::TensorFlow::Libtensorflow::Manual::Notebook::InferenceUsingTFHubMobileNetV2Model>: image classification tutorial

This tutorial demonstrates using a pre-trained SavedModel and creating a L<AI::TensorFlow::Libtensorflow::Session> with the
L<LoadFromSavedModel|AI::TensorFlow::Libtensorflow::Session/LoadFromSavedModel>
method. It also demonstrates how to prepare image data for use as an input C<TFTensor>.

=item L<InferenceUsingTFHubEnformerGeneExprPredModel|AI::TensorFlow::Libtensorflow::Manual::Notebook::InferenceUsingTFHubEnformerGeneExprPredModel>: gene expression prediction tutorial

lib/AI/TensorFlow/Libtensorflow/OperationDescription.pm  view on Meta::CPAN

# ABSTRACT: Operation being built
$AI::TensorFlow::Libtensorflow::OperationDescription::VERSION = '0.0.7';
use strict;
use warnings;
use namespace::autoclean;
use AI::TensorFlow::Libtensorflow::Lib qw(arg);
use AI::TensorFlow::Libtensorflow::Lib::FFIType::Variant::PackableArrayRef;

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_attr_string_buffer'
);
$ffi->load_custom_type('AI::TensorFlow::Libtensorflow::Lib::FFIType::TFPtrPtrLenSizeArrayRefScalar'
        => 'tf_attr_string_list'
);
$ffi->load_custom_type(PackableArrayRef('Int64ArrayRef', pack_type => 'q')
        => 'tf_attr_int_list'
);
$ffi->load_custom_type(PackableArrayRef('Float32ArrayRef', pack_type => 'f')
	=> 'tf_attr_float_list'
);
$ffi->load_custom_type(PackableArrayRef('BoolArrayRef', pack_type => 'C')
	=> 'tf_attr_bool_list',
);

$ffi->attach( [ 'NewOperation' => 'New' ] => [
	arg 'TF_Graph' => 'graph',
	arg 'string'   => 'op_type',
	arg 'string'   => 'oper_name',
] => 'TF_OperationDescription' => sub {
	my ($xs, $class, @rest) = @_;
	$xs->(@rest);
});

$ffi->attach( [ 'NewOperationLocked' => 'NewLocked' ] => [
	arg 'TF_Graph' => 'graph',
	arg 'string'   => 'op_type',
	arg 'string'   => 'oper_name',
] => 'TF_OperationDescription' );

$ffi->attach( 'SetDevice' => [
	arg 'TF_OperationDescription' => 'desc',
	arg 'string' => 'device',
] => 'void');

$ffi->attach( 'AddInput' => [
	arg 'TF_OperationDescription' => 'desc',

lib/AI/TensorFlow/Libtensorflow/Output.pm  view on Meta::CPAN

	# padding to make sizeof(record) == 16
	# but only on machines where sizeof(opaque) is 8 bytes
	# See also:
	#   Convert::Binary::C->new( Alignment => 8 )
	#     ->parse( ... )
	#     ->sizeof( ... )
	$ffi->sizeof('opaque') == 8 ? (
		'char[4]' => ':',
	) : (),
);
$ffi->type('record(AI::TensorFlow::Libtensorflow::Output)', 'TF_Output');

sub New {
	my ($class, $args) = @_;

	my $record = $class->new({
		_oper => $ffi->cast( 'TF_Operation', 'opaque', delete $args->{oper} ),
		_index => delete $args->{index},
	});
}

lib/AI/TensorFlow/Libtensorflow/Output.pm  view on Meta::CPAN

			$record;
		} 0..$array->count-1
	]
}
sub _copy_to_other {
	my ($class, $this, $that) = @_;
       $that->_oper ($this->_oper);
       $that->_index($this->_index);
}

$ffi->load_custom_type(
	RecordArrayRef( 'OutputArrayPtr',
		record_module => __PACKAGE__, with_size => 0,
	),
	=> 'TF_Output_array');
$ffi->load_custom_type(
	RecordArrayRef( 'OutputArrayPtrSz',
		record_module => __PACKAGE__, with_size => 1,
	),
	=> 'TF_Output_array_sz');

use overload
	'""' => \&_op_stringify;

sub _op_stringify {
	join ":", (

lib/AI/TensorFlow/Libtensorflow/Session.pm  view on Meta::CPAN

		arg 'TF_SessionOptions' => 'opt',
		arg 'TF_Status' => 'status',
	],
	=> 'TF_Session' => sub {
		my ($xs, $class, @rest) = @_;
		return $xs->(@rest);
	});

$ffi->attach( [ 'LoadSessionFromSavedModel' => 'LoadFromSavedModel' ] => [
    arg TF_SessionOptions => 'session_options',
    arg opaque => { id => 'run_options', ffi_type => 'TF_Buffer', maybe => 1 },
    arg string => 'export_dir',
    arg 'string[]' => 'tags',
    arg int => 'tags_len',
    arg TF_Graph => 'graph',
    arg opaque => { id => 'meta_graph_def', ffi_type => 'TF_Buffer', maybe => 1 },
    arg TF_Status => 'status',
] => 'TF_Session' => sub {
	my ($xs, $class, @rest) = @_;
	my ( $session_options,
		$run_options,
		$export_dir, $tags,
		$graph, $meta_graph_def,
		$status) = @rest;


lib/AI/TensorFlow/Libtensorflow/Session.pm  view on Meta::CPAN

		$graph, $meta_graph_def,
		$status
	);
} );

$ffi->attach( [ 'SessionRun' => 'Run' ] =>
	[
		arg 'TF_Session' => 'session',

		# RunOptions
		arg 'opaque'  => { id => 'run_options', ffi_type => 'TF_Buffer', maybe => 1 },

		# Input TFTensors
		arg 'TF_Output_struct_array' => 'inputs',
		arg 'TF_Tensor_array' => 'input_values',
		arg 'int'             => 'ninputs',

		# Output TFTensors
		arg 'TF_Output_struct_array' => 'outputs',
		arg 'TF_Tensor_array' => 'output_values',
		arg 'int'             => 'noutputs',

		# Target operations
		arg 'opaque'         => { id => 'target_opers', ffi_type => 'TF_Operation_array', maybe => 1 },
		arg 'int'            => 'ntargets',

		# RunMetadata
		arg 'opaque'      => { id => 'run_metadata', ffi_type => 'TF_Buffer', maybe => 1 },

		# Output status
		arg 'TF_Status' => 'status',
	],
	=> 'void' => sub {
		my ($xs,
			$self,
			$run_options,
			$inputs , $input_values,
			$outputs, $output_values,

lib/AI/TensorFlow/Libtensorflow/Session.pm  view on Meta::CPAN


$ffi->attach([ 'SessionPRunSetup' => 'PRunSetup' ] => [
    arg TF_Session => 'session',
    # Input names
    arg TF_Output_struct_array => 'inputs',
    arg int => 'ninputs',
    # Output names
    arg TF_Output_struct_array => 'outputs',
    arg int => 'noutputs',
    # Target operations
    arg opaque => { id => 'target_opers', ffi_type => 'TF_Operation_array', maybe => 1 },
    arg int => 'ntargets',
    # Output handle
    arg 'opaque*' => { id => 'handle', ffi_type => 'string*', window =>  1 },
    # Output status
    arg TF_Status => 'status',
] => 'void' => sub {
	my ($xs, $session, $inputs, $outputs, $target_opers, $status) = @_;

	$inputs  = AI::TensorFlow::Libtensorflow::Output->_as_array( @$inputs );
	$outputs = AI::TensorFlow::Libtensorflow::Output->_as_array( @$outputs );

	my $handle;
	$xs->($session,

lib/AI/TensorFlow/Libtensorflow/Session.pm  view on Meta::CPAN

	arg TF_Output_struct_array => 'inputs',
	arg TF_Tensor_array => 'input_values',
	arg int => 'ninputs',

	# Outputs
	arg TF_Output_struct_array => 'outputs',
	arg TF_Tensor_array => 'output_values',
	arg int => 'noutputs',

	# Targets
	arg 'opaque*' => { id => 'target_opers', ffi_type => 'TF_Operation_array', maybe => 1 },
	arg int => 'ntargets',

	arg TF_Status => 'status',
] => 'void' => sub {
	my ($xs, $session, $handle_obj,
		$inputs, $input_values,
		$outputs, $output_values,
		$target_opers,
		$status) = @_;

lib/AI/TensorFlow/Libtensorflow/Status.pm  view on Meta::CPAN

	[ RESOURCE_EXHAUSTED  => 8 ],
	[ FAILED_PRECONDITION => 9 ],
	[ ABORTED             => 10 ],
	[ OUT_OF_RANGE        => 11 ],
	[ UNIMPLEMENTED       => 12 ],
	[ INTERNAL            => 13 ],
	[ UNAVAILABLE         => 14 ],
	[ DATA_LOSS           => 15 ],
);

$ffi->load_custom_type('::Enum', 'TF_Code',
	{ rev => 'int', package => __PACKAGE__ },
	@_TF_CODE
);

my %_TF_CODE_INT_TO_NAME = map { reverse @$_ } @_TF_CODE;

#}}}

$ffi->attach( [ 'NewStatus' => 'New' ] => [] => 'TF_Status' );

lib/AI/TensorFlow/Libtensorflow/TString.pm  view on Meta::CPAN

package AI::TensorFlow::Libtensorflow::TString;
# ABSTRACT: A variable-capacity string type
$AI::TensorFlow::Libtensorflow::TString::VERSION = '0.0.7';
use strict;
use warnings;
use namespace::autoclean;
use AI::TensorFlow::Libtensorflow::Lib qw(arg);
use FFI::Platypus::Memory qw(malloc free);

my $ffi = AI::TensorFlow::Libtensorflow::Lib->ffi;
$ffi->mangler(AI::TensorFlow::Libtensorflow::Lib->mangler_default);

### From <tensorflow/tsl/platform/ctstring_internal.h>
#// _Static_assert(sizeof(TF_TString) == 24);
use constant SIZEOF_TF_TString => 24;


### From <tensorflow/tsl/platform/ctstring_internal.h>
# typedef enum TF_TString_Type {  // NOLINT
#   TF_TSTR_SMALL = 0x00,
#   TF_TSTR_LARGE = 0x01,
#   TF_TSTR_OFFSET = 0x02,
#   TF_TSTR_VIEW = 0x03,
#   TF_TSTR_TYPE_MASK = 0x03
# } TF_TString_Type;

sub _CREATE {
	my ($class) = @_;
	my $pointer = malloc SIZEOF_TF_TString;

lib/AI/TensorFlow/Libtensorflow/TString.pm  view on Meta::CPAN

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

AI::TensorFlow::Libtensorflow::TString - A variable-capacity string type

=head1 SYNOPSIS

  use aliased 'AI::TensorFlow::Libtensorflow::TString';

=head1 CONSTRUCTORS

=head2 Init

  my $tstr = TString->Init;

lib/AI/TensorFlow/Libtensorflow/TString.pm  view on Meta::CPAN

B<C API>: L<< C<TF_StringAssignView>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_StringAssignView >>

=head2 GetDataPointer

TODO API question: Should this be an opaque or a window()?

B<C API>: L<< C<TF_StringGetDataPointer>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_StringGetDataPointer >>

=head2 GetType

TODO API question: Add enum for TF_TString_Type return type?

B<C API>: L<< C<TF_StringGetType>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_StringGetType >>

=head2 GetSize

B<C API>: L<< C<TF_StringGetSize>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_StringGetSize >>

=head2 GetCapacity

B<C API>: L<< C<TF_StringGetCapacity>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_StringGetCapacity >>

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} ) {

lib/AI/TensorFlow/Libtensorflow/Tensor.pm  view on Meta::CPAN

	[
		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,

lib/AI/TensorFlow/Libtensorflow/Tensor.pm  view on Meta::CPAN

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

AI::TensorFlow::Libtensorflow::Tensor - A multi-dimensional array of elements of a single data type

=head1 SYNOPSIS

  use aliased 'AI::TensorFlow::Libtensorflow::Tensor' => 'Tensor';
  use AI::TensorFlow::Libtensorflow::DataType qw(FLOAT);
  use List::Util qw(product);

  my $dims = [3, 3];

  # Allocate a 3 by 3 ndarray of type FLOAT
  my $t = Tensor->Allocate(FLOAT, $dims);
  is $t->ByteSize, product(FLOAT->Size, @$dims), 'correct size';

  my $scalar_dims = [];
  my $scalar_t = Tensor->Allocate(FLOAT, $scalar_dims);
  is $scalar_t->ElementCount, 1, 'single element';
  is $scalar_t->ByteSize, FLOAT->Size, 'single FLOAT';

=head1 DESCRIPTION

A C<TFTensor> is an object that contains values of a
single type arranged in an n-dimensional array.

For types other than L<STRING|AI::TensorFlow::Libtensorflow::DataType/STRING>,
the data buffer is stored in L<row major order|https://en.wikipedia.org/wiki/Row-_and_column-major_order>.

Of note, this is different from the definition of I<tensor> used in
mathematics and physics which can also be represented as a
multi-dimensional array in some cases, but these tensors are
defined not by the representation but by how they transform. For
more on this see

=over 4

lib/AI/TensorFlow/Libtensorflow/Tensor.pm  view on Meta::CPAN


=back

=head1 CONSTRUCTORS

=head2 New

=over 2

C<<<
New( $dtype, $dims, $data, $deallocator, $deallocator_arg )
>>>

=back

Creates a C<TFTensor> from a data buffer C<$data> with the given specification
of data type C<$dtype> and dimensions C<$dims>.

  # Create a buffer containing 0 through 8 single-precision
  # floating-point data.
  my $data = pack("f*",  0..8);

  $t = Tensor->New(
    FLOAT, [3,3], \$data, sub { undef $data }, undef
  );

  ok $t, 'Created 3-by-3 float TFTensor';

Implementation note: if C<$dtype> is not a
L<STRING|AI::TensorFlow::Libtensorflow::DataType/STRING>
or
L<RESOURCE|AI::TensorFlow::Libtensorflow::DataType/RESOURCE>,
then the pointer for C<$data> is checked to see if meets the
TensorFlow's alignment preferences. If it does not, the
contents of C<$data> are copied into a new buffer and
C<$deallocator> is called during construction.
Otherwise the contents of C<$data> are not owned by the returned
C<TFTensor>.

B<Parameters>

=over 4

=item L<TFDataType|AI::TensorFlow::Libtensorflow::Lib::Types/TFDataType> $dtype

DataType for the C<TFTensor>.

=item L<Dims|AI::TensorFlow::Libtensorflow::Lib::Types/Dims> $dims

An C<ArrayRef> of the size of each dimension.

=item ScalarRef[Bytes] $data

Data buffer for the contents of the C<TFTensor>.

lib/AI/TensorFlow/Libtensorflow/Tensor.pm  view on Meta::CPAN


=back

B<C API>: L<< C<TF_NewTensor>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_NewTensor >>

=head2 Allocate

=over 2

C<<<
Allocate($dtype, $dims, $len = )
>>>

=back

This constructs a C<TFTensor> with the memory for the C<TFTensor>
allocated and owned by the C<TFTensor> itself. Unlike with L</New>
the allocated memory satisfies TensorFlow's alignment preferences.

See L</Data> for how to write to the data buffer.

  use AI::TensorFlow::Libtensorflow::DataType qw(DOUBLE);

  # Allocate a 2-by-2 ndarray of type DOUBLE
  $dims = [2,2];
  my $t = Tensor->Allocate(DOUBLE, $dims, product(DOUBLE->Size, @$dims));

B<Parameters>

=over 4

=item L<TFDataType|AI::TensorFlow::Libtensorflow::Lib::Types/TFDataType> $dtype

DataType for the C<TFTensor>.

=item L<Dims|AI::TensorFlow::Libtensorflow::Lib::Types/Dims> $dims

An C<ArrayRef> of the size of each dimension.

=item size_t $len [optional]

Number of bytes for the data buffer. If a value is not given,
this is calculated from C<$dtype> and C<$dims>.

=back

B<Returns>

=over 4

=item L<TFTensor|AI::TensorFlow::Libtensorflow::Lib::Types/TFTensor>

A C<TFTensor> with memory allocated for data buffer.

lib/AI/TensorFlow/Libtensorflow/Tensor.pm  view on Meta::CPAN

B<C API>: L<< C<TF_TensorByteSize>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_TensorByteSize >>

=head2 Type

B<Returns>

=over 4

=item L<TFDataType|AI::TensorFlow::Libtensorflow::Lib::Types/TFDataType>

The C<TFTensor>'s data type.

=back

B<C API>: L<< C<TF_TensorType>|AI::TensorFlow::Libtensorflow::Manual::CAPI/TF_TensorType >>

=head2 NumDims

B<Returns>

=over 4

maint/inc/Pod/Elemental/Transformer/TF_Sig.pm  view on Meta::CPAN


  return unless $para->isa('Pod::Elemental::Element::Pod5::Region')
         and $para->format_name =~ /^(?:param|returns|signature)$/;

  confess("list regions must be pod (=begin :" . $self->format_name . ")")
    unless $para->is_pod;

  return 1;
}

my %region_types = (
  'signature' => 'Signature',
  'param'     => 'Parameters',
  'returns'   => 'Returns',
);

around _expand_list_paras => sub {
  my ($orig, $self, $para) = @_;

  my $is_list_type = $para->format_name =~ /^(?:param|returns)$/;

  if( $is_list_type ) {
    die "Need description list for @{[ $para->as_pod_string ]}"
      unless $para->children->[0]->content =~ /^=/;
  }
  my $prefix;
  if( $para->isa('Pod::Elemental::Element::Pod5::Region')
    && exists $region_types{$para->format_name}
  ) {
    $prefix = Pod::Elemental::Element::Pod5::Ordinary->new({
      content => "B<@{[ $region_types{$para->format_name} ]}>",
    });
  }

  my @replacements;
  if( $is_list_type ) {
    @replacements = $orig->($self, $para);
  } else {
    undef $prefix;
    push @replacements, Pod::Elemental::Element::Pod5::Ordinary
      ->new( { content => do { my $v = <<EOF; chomp $v; $v } });
=over 2

C<<<
@{[ join("\n", map { $_->content } $para->children->@*) ]}
>>>

maint/inc/Pod/Elemental/Transformer/TF_Sig.pm  view on Meta::CPAN

  @replacements;
};

sub __paras_for_num_marker { die "only support definition lists" }
sub __paras_for_bul_marker { die "only support definition lists" }

around __paras_for_def_marker => sub {
  my ($orig, $self, $rest) = @_;

  my $ffi = AI::TensorFlow::Libtensorflow::Lib->ffi;
  my $type_library = 'AI::TensorFlow::Libtensorflow::Lib::Types';
  my @types = ($rest);
  my $process_type = sub {
    my ($type) = @_;
    my $new_type_text = $type;
    my $info;
    if( eval { $info->{TT} = t($type); 1 }
      || eval { $info->{FFI} = $ffi->type_meta($type); 1 } ) {
      if( $info->{TT} && $info->{TT}->library eq $type_library ) {
        $new_type_text = "L<$type|$type_library/$type>";
      }
    } else {
      die "Could not find type constraint or FFI::Platypus type $type";
    }

    $new_type_text;
  };

  my $type_re = qr{
    \A (?<ws>\s*) (?<type> \w+)
  }xm;
  $rest =~ s[$type_re]{$+{ws} . $process_type->($+{type}) }ge;

  my @replacements = $orig->($self, $rest);

  @replacements;
};

1;

maint/process-capi.pl  view on Meta::CPAN


		=cut

		EOF

		my $output = $self->lib_path->child(module_notional_filename($doc_name) =~ s/\.pm$/.pod/r );
		$output->parent->mkpath;
		$output->spew_utf8($pod);
	}

	lazy typedef_struct_data => method() {
		my $re = qr{
			(?<opaque>
				^
				typedef      \s+
				struct       \s+
				(?<name>\w+) \s+
				\k<name>     \s*
				;
			)
			|
			(?<transparent>
				^
				typedef      \s+
				struct       \s+
				(?<name>\w+) \s+
				\{
				[^\}]+
				\}           \s+
				\k<name>     \s*
				;
			)
		}xm;
		$self->_process_re($re);
	};

	method check_types() {
		my @data = $self->typedef_struct_data->@*;
		my %types = map { $_ => 1 } AI::TensorFlow::Libtensorflow::Lib->ffi->types;
		my %part;
		@part{qw(todo done)} = part { exists $types{$_} } uniq map { $_->{name} } @data;
		use DDP; p %part;
	}

	method check_functions($first_arg = undef) {
		my $functions = AI::TensorFlow::Libtensorflow::Lib->ffi->_attached_functions;
		my @dupes = map { $_->[0]{c} }
			grep { @$_ != 1 } values $functions->%*;
		die "Duplicated functions @dupes" if @dupes;

		my @data = $self->fdecl_data->@*;

maint/process-capi.pl  view on Meta::CPAN

				! defined $first_arg ||
				$_->{fdecl} =~ /\(\s*\Q$first_arg\E\s*\*/
			)
		} @data;
		say "Missing function:";
		use DDP; p $first_missing_function;
	}

	method run() {
		$self->generate_capi_funcs;
		#$self->check_types;
		$self->check_functions;
	}

	subcommand 'generate-capi-docs' => method(@) {
		$self->generate_capi_funcs;
	};

	subcommand 'check-types' => method(@) {
		$self->check_types;
	};

	subcommand 'check-functions' => method(@) {
		if( $_[0] eq '--help' ) {
			print STDERR "$0 check-functions [TYPE]\n";
			exit;
		}
		$self->check_functions(shift @_);
	};

perlcritic.rc  view on Meta::CPAN

theme = ( core + pbp + security + maintenance ) * bugs
include = CodeLayout::ProhibitTrailingWhitespace CodeLayout::RequireConsistentNewlines

[-Subroutines::ProhibitSubroutinePrototypes]

# alternate that works better with dzil ::PkgVersion
[-TestingAndDebugging::RequireUseStrict]
[-TestingAndDebugging::RequireUseWarnings]
[Community::StrictWarnings]
extra_importers = Test2::V0

# vim: ft=dosini

t/lib/TF_Utils.pm  view on Meta::CPAN


	my $p_dataref = $p->get_dataref;
	my $tensor = AI::TensorFlow::Libtensorflow::Tensor->New(
		FLOAT, [ $p->dims ], $p_dataref, $pdl_closure
	);

	$tensor;
}

sub Placeholder {
	my ($graph, $status, $name, $dtype) = @_;
	$name ||= 'feed';
	$dtype ||= INT32;
	my $desc = AI::TensorFlow::Libtensorflow::OperationDescription->New($graph, 'Placeholder', $name);
	$desc->SetAttrType('dtype', $dtype);
	my $op = $desc->FinishOperation($status);
	AssertStatusOK($status);
	$op;
}

sub Const {
	my ($graph, $status, $name, $t) = @_;
	my $desc = AI::TensorFlow::Libtensorflow::OperationDescription->New($graph, 'Const', $name);
	$desc->SetAttrTensor('value', $t, $status);
	$desc->SetAttrType('dtype', $t->Type);
	my $op = $desc->FinishOperation($status);
	AssertStatusOK($status);
	$op;
}

my %dtype_to_pack = (
	FLOAT  => 'f',
	DOUBLE => 'd',
	INT32  => 'l',
	INT8   => 'c',
	BOOL   => 'c',
);

use FFI::Platypus::Buffer qw(scalar_to_pointer);
use FFI::Platypus::Memory qw(memcpy);

sub ScalarConst {
	my ($graph, $status, $name, $dtype, $value) = @_;
	$name ||= 'scalar';
	my $t = AI::TensorFlow::Libtensorflow::Tensor->Allocate($dtype, []);
	die "Pack format for $dtype is unknown" unless exists $dtype_to_pack{$dtype};
	my $data = pack $dtype_to_pack{$dtype} . '*', $value;
	memcpy scalar_to_pointer(${ $t->Data }),
		 scalar_to_pointer($data),
		 $t->ByteSize;
	return Const($graph, $status, $name, $t);
}


use AI::TensorFlow::Libtensorflow::Lib::Types qw(TFOutput TFOutputFromTuple);
use Types::Standard qw(HashRef);

t/lib/TF_Utils.pm  view on Meta::CPAN

	my $desc = AI::TensorFlow::Libtensorflow::OperationDescription->New(
		$graph, "Neg", $name);
	my $neg_input = $TFOutput->coerce([$n => 0]);
	$desc->AddInput($neg_input);
	my $op = $desc->FinishOperation($s);
	AssertStatusOK($s);
	$op;
}

sub AnyTensor {
	my ($dtype, $v) = @_;
	die "Pack format for $dtype is unknown" unless exists $dtype_to_pack{$dtype};
	if( ! ref $v ) {
		my $t = AI::TensorFlow::Libtensorflow::Tensor->Allocate( $dtype, [] );
		memcpy scalar_to_pointer( ${ $t->Data } ),
			scalar_to_pointer(pack($dtype_to_pack{$dtype}, $v)), $dtype->Size;
		return $t;
	} elsif( ref $v eq 'ARRAY' ) {
		my $n = @$v;
		my $t = AI::TensorFlow::Libtensorflow::Tensor->Allocate( $dtype, [$n] );
		memcpy scalar_to_pointer( ${ $t->Data } ),
			scalar_to_pointer(pack("$dtype_to_pack{$dtype}*", @$v)), $n * $dtype->Size;
		return $t;
	}
}

sub Int8Tensor {
	return AnyTensor(INT8, @_);
}

sub Int32Tensor {
	return AnyTensor(INT32, @_);

t/lib/TF_Utils.pm  view on Meta::CPAN


	my $s = AI::TensorFlow::Libtensorflow::Status->New;
	my $graph;
	if( ! $session ) {
		my $opts = AI::TensorFlow::Libtensorflow::SessionOptions->New;
		$graph = AI::TensorFlow::Libtensorflow::Graph->New;
		$session ||= AI::TensorFlow::Libtensorflow::Session->New($graph, $opts, $s);
	}

	my $device_list = $session->ListDevices($s);
	my $device_idx = first { my $type = $device_list->Type( $_, $s ) eq 'GPU' } 0..$device_list->Count - 1;

	return "" unless $device_idx;

	return $device_list->Name( $device_idx, $s );
}

sub DumpDevices {
	my ($session) = @_;

	my $s = AI::TensorFlow::Libtensorflow::Status->New;



( run in 3.646 seconds using v1.01-cache-2.11-cpan-df04353d9ac )