PDL

 view release on metacpan or  search on metacpan

lib/PDL/API.pod  view on Meta::CPAN


Also described is the new (as of PDL 2.058) access to PDL operations
via C functions, which the XS functions now call.

=head2 Creating an ndarray manually from Perl

Sometimes you want to create an ndarray I<manually>
from binary data. You can do that at the Perl level.
Examples in the distribution include some of the
IO routines. The code snippet below illustrates the
required steps.

   use Carp;
   sub mkmyndarray {
     my $class = shift;
     my $pdl  = $class->new;
     $pdl->set_datatype($PDL_B);
     $pdl->setdims([1,3,4]);
     my $dref = $pdl->get_dataref();
     # read data directly from file
     open my $file, '<data.dat' or die "couldn't open data.dat";
     my $len = $pdl->nelems*PDL::Core::howbig($pdl->get_datatype);
     croak "couldn't read enough data" if
       read( $file, $$dref, $len) != $len;
     close $file;
     $pdl->upd_data();
     return $pdl;
   }

=head2 Creating an ndarray in C

The following example creates an ndarray at the C level.
We use the C<Inline> module which is a good way to interface
Perl and C, using the C<with> capability in L<Inline> 0.68+.

Note that to create a "scalar" ndarray (with no dimensions at all,
and a single element), just pass a zero-length C<dims> array, with
C<ndims> as zero.

   use PDL::LiteF;

   $x = myfloatseq(); # exercise our C ndarray constructor

   print $x->info,"\n";

   use Inline with => 'PDL';
   use Inline C;
   Inline->init; # useful if you want to be able to 'do'-load this script

   __DATA__

   __C__

   static pdl* new_pdl(int datatype, PDL_Indx dims[], int ndims)
   {
     pdl *p = PDL->pdlnew();
     if (!p) return p;
     pdl_error err = PDL->setdims(p, dims, ndims);  /* set dims */
     if (err.error) { PDL->destroy(p); return NULL; }
     p->datatype = datatype;         /* and data type */
     err = PDL->allocdata (p);       /* allocate the data chunk */
     if (err.error) { PDL->destroy(p); return NULL; }
     return p;
   }

   pdl* myfloatseq()
   {
     PDL_Indx dims[] = {5,5,5};
     pdl *p = new_pdl(PDL_F,dims,3);
     if (!p) return p;
     PDL_Float *dataf = (PDL_Float *) p->data;
     PDL_Indx i; /* dimensions might be 64bits */

     for (i=0;i<5*5*5;i++)
       dataf[i] = i; /* the data must be initialized ! */
     return p;
   }

=head2 Wrapping your own data into an ndarray

Sometimes you obtain a chunk of data from another
source, for example an image processing library, etc.
All you want to do in that case is wrap your data
into an ndarray struct at the C level. Examples using this approach
can be found in the IO modules (where FastRaw and FlexRaw
use it for mmapped access) and the Gimp Perl module (that
uses it to wrap Gimp pixel regions into ndarrays).
The following script demonstrates a simple example:

   use PDL::LiteF;
   use PDL::Core::Dev;

   $y = mkndarray();

   print $y->info,"\n";

   imag1 $y;

   use Inline with => 'PDL';
   use Inline C;
   Inline->init;

   __DATA__

   __C__

   /* wrap a user supplied chunk of data into an ndarray
    * You must specify the dimensions (dims,ndims) and
    * the datatype (constants for the datatypes are declared
    * in pdl.h; e.g. PDL_B for byte type, etc)
    *
    * when the created ndarray 'p' is destroyed on the
    * Perl side the function passed as the 'delete_magic'
    * parameter will be called with the pointer to the pdl structure
    * and the 'delparam' argument.
    * This gives you an opportunity to perform any clean up
    * that is necessary. For example, you might have to
    * explicitly call a function to free the resources
    * associated with your data pointer.
    * At the very least 'delete_magic' should zero the ndarray's data pointer:
    *

lib/PDL/API.pod  view on Meta::CPAN

and C<PDL_BOOT> and use that same identifier in your own code.
E.g., continuing from the example above:

  pdl *p = PDL_Corep->pdlnew();

=head2 Some selected core routines explained

The full definition of the C<Core> struct can be found in the file
F<pdlcore.h>. In the following the most frequently used member
functions of this struct are briefly explained.

=over 5

=item *

C<pdl *SvPDLV(SV *sv)>

=item *

C<pdl *SetSV_PDL(SV *sv, pdl *it)>

=item *

C<pdl *pdlnew()>

C<pdlnew> returns an empty pdl object that is initialised like a "null"
but with no data. Example:

  pdl *p = PDL->pdlnew();
  if (!p) return p;
  pdl_error err = PDL->setdims(p, dims, ndims);  /* set dims */
  if (err.error) { PDL->destroy(p); return NULL; }
  p->datatype = PDL_B;

Returns C<NULL> if a problem occurred, so check for that.

=item *

C<pdl *null()>

Returns C<NULL> if a problem occurred, so check for that.

=item *

C<SV *copy(pdl* p, char* )>

=item *

C<void *smalloc(STRLEN nbytes)>

=item *

C<int howbig(int pdl_datatype)>

=item *

C<pdl_error add_deletedata_magic(pdl *p, void (*func)(pdl*, int), int param)>

=item *

C<pdl_error allocdata(pdl *p)>

=item *

C<pdl_error make_physical(pdl *p)>

=item *

C<pdl_error make_physdims(pdl *p)>

=item *

C<pdl_error make_physvaffine(pdl *p)>

=item *

C<void pdl_barf(const char* pat,...)> and
C<void pdl_warn(const char* pat,...)>

These are C-code equivalents of C<barf> and C<warn>. They include special handling of error or warning
messages during pthreading (i.e. processor multi-threading) that defer the messages until after pthreading
is completed. When pthreading is complete, perl's C<barf> or C<warn> is called with the deferred messages. This
is needed to keep from calling perl's C<barf> or C<warn> during pthreading, which can cause segfaults.

Note that C<barf> and C<warn> have been redefined (using c-preprocessor macros) in pdlcore.h to C<< PDL->barf >>
and C<< PDL->warn >>. This is to keep any XS or PP code from calling perl's C<barf> or C<warn> directly, which can
cause segfaults during pthreading.

See L<PDL::ParallelCPU> for more information on pthreading.

B<NB> As of 2.064, it is B<highly recommended> that you do not call
C<barf> at all in PP code, but instead use C<$CROAK()>. This will return
a C<pdl_error> which will transparently be used to throw the correct
exception in Perl code, but can be handled suitably by non-Perl callers.

=item *

  converttype

Used by C<set_datatype> to change an ndarray's type, converting and
possibly re-allocating the data if a different size. If the ndarray's
C<badflag> was set, its C<badvalue> will become the default for the
new type. Bad values will still be bad.
As of 2.093, will physicalise its ndarray.

=item *

  converttypei_new

Affine transformation used only by C<get_convertedpdl> to convert an
ndarray's type. Not bad-value aware.

=item *

  get_convertedpdl

Used by L<PDL::Core/convert>.

=item *

  affine_new



( run in 0.579 second using v1.01-cache-2.11-cpan-39bf76dae61 )