Very belatedly – yes, Bryan does remember correctly. Also, you could guarantee 
the “physical”ness of the ndarray on the C side, with this at the start of your 
C function:

  PDL->make_physical(im);

But the most idiomatic way by far, if you’re already doing Inline::*, is 
Inline::Pdlpp. For a working (albeit somewhat complex) example, see posts here 
about John Walker’s floating-point benchmarks done in PDL.

Best regards,
Ed

From: Bryan Jurish<mailto:[email protected]>
Sent: 19 June 2020 14:26
To: Derek Lamb<mailto:[email protected]>
Cc: perldl<mailto:[email protected]>
Subject: Re: [Pdl-general] How to change a child piddle's data in C?

greetings all,

+1 re David's suggestion of PDL::PP ... there's also an 
Inline::Pdlpp<https://metacpan.org/pod/Inline::Pdlpp> on (meta)cpan which has 
worked well for me in the past.

If your "proper" C code is sneakier than times_ten() and needs batch access to 
whole memory regions, you might try calling $im2->make_physical() before you 
pass it to (the sneaky variant of) times_ten() ... iirc, pdl dataflow should 
then take care of updating the parent slice.

marmosets,
  Bryan

On Fri, Jun 19, 2020 at 3:13 PM David Mertens 
<[email protected]<mailto:[email protected]>> wrote:
Hello Derek,

As I recall (but this is a hazy recollection, Craig could answer this with 
greater authority and detail), the PDL version of the method will do quite a 
bit of work for you before calling pdl_times_ten_readdata. In particular, it'll 
make physical copies of all non-contiguous slice piddles, i.e. those generated 
by where. However, your slice should be is "affine", so I'm a bit surprised 
that the "dimincs" piece isn't working as expected.

I'll echo what Ingo said: why not create a PDL::PP wrapper? There is a handy 
example 
here<http://pdl.perl.org/PDLdocs/PP.html#Interfacing-your-own-library-functions-using-PP>.
 Otherwise your C code will probably have to consult the "vafftrans" member of 
the PDL object and figure things out on its own, something I've never done 
before. For more hints on where to get started, consulate the paragraph just 
before section 6 on page 38 of Practical Magick with C, PDL and 
PDL::PP<https://www.boulder.swri.edu/~deforest/ewExternalFiles/PP-practical-magick.pdf>.

David

On Fri, Jun 19, 2020 at 2:23 AM Derek Lamb 
<[email protected]<mailto:[email protected]>> wrote:
Question: Is there a straightforward way to operate on a piddle in C without 
knowing whether it's a physical or a child piddle, just like we do in PDL?  And 
if so, what is it?

As background: I have a subroutine, implemented in C, called from Perl using 
Inline::C.  It takes an arbitrary-sized array ref of 2D-piddles as input, and 
modifies the piddles, like so:

###
my $aref = [$pdl1, $pdl2, $pdl3];
my_sub( $aref );
###

So far, so good.  That is, until I accidentally threw a child (non-physical) 
piddle at it:

###
my $aref = [$big_3D_pdl->dog];
my_sub( $aref );
###

Then, at best, my_sub completes successfully but does not change any of the 
data in the piddles in $aref.  Other times it segfaults.  It has no trouble 
changing the data in $aref in the first example, when the piddles are physical.

For simplicity, here is an example that doesn't use array refs, just takes a 
single piddle as input.  When called on a physical piddle $im0, it works fine, 
but does not change the data in $im2 and frequently segfaults.  This script 
contains a subroutine "times_ten" that just multiplies each element of the 
piddle by 10.

###
use strict;
use warnings;
use PDL::LiteF;
use PDL::Core::Dev;
use PDL::Dbg;
$PDL::debug=1; #for px calls

my $im0 = sequence(5,4);
my $im1 = sequence(8,7);
my $im2 = $im1->slice("0:3,0:2");

$_->px foreach ($im0,$im2);

times_ten($im0);
times_ten($im2);

print "\nNow that I'm done, \$im0 is:\n$im0\n";
print "\nNow that I'm done, \$im2 is:\n$im2\n";

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

__DATA__

__C__

void times_ten(pdl* im){

    printf("im xsize = %ld, ysize = %ld\n",im->dims[0],im->dims[1]);
    PDL_Double *data = (PDL_Double *) im->data;
    for (PDL_Indx x = 0; x < im->dims[0]; x++){
      for (PDL_Indx y = 0; y < im->dims[1]; y++){
        PDL_Indx offset = x * im->dimincs[0] + y * im->dimincs[1];
        data[offset] *= 10;
      }
    }
return;
}
###

What I would like is something near the beginning of the C code that abstracts 
the input piddle so the subsequent code doesn't care whether the input is 
physical or child.

I made a similar example using Inline::Pdlpp and looked at the generated C 
code, and there in the subroutine "pdl_times_ten_readdata", in the THREADLOOP 
section is code that seems to take care of the pointer addressing whether the 
input piddle is physical or a virtual/child piddle.  I was hoping for something 
less involved than a bunch of "__privtrans" lines—it's a bit hard for the 
casual reader to understand what's going on.  (That "casual reader" may be me, 
in 6 or 12 months!)  Is there a clean way to do this, or is it best in this 
case to make sure that the input piddles are always physical?

thanks much,
Derek

_______________________________________________
pdl-general mailing list
[email protected]<mailto:[email protected]>
https://lists.sourceforge.net/lists/listinfo/pdl-general


--
 "Debugging is twice as hard as writing the code in the first place.
  Therefore, if you write the code as cleverly as possible, you are,
  by definition, not smart enough to debug it." -- Brian Kernighan
_______________________________________________
pdl-general mailing list
[email protected]<mailto:[email protected]>
https://lists.sourceforge.net/lists/listinfo/pdl-general


--
Bryan Jurish                           "There is *always* one more bug."
[email protected]<mailto:[email protected]>         -Lubarsky's Law 
of Cybernetic Entomology

_______________________________________________
pdl-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/pdl-general

Reply via email to