Skip to content

Commit db6255e

Browse files
committed
add whichND_both
1 parent 329d695 commit db6255e

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

Changes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
- badflag now not propagated back to inputs if set on outputs (#517)
2828
- add new_around_pointer (#505) - thanks @chrisarg for idea
2929
- add do_print to perldl to match pdl2
30+
- add whichND_both - thanks @guillepo for inspiration
3031

3132
2.098 2025-01-03
3233
- fix Windows build problems

lib/PDL/Primitive.pd

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3388,6 +3388,8 @@ C<$c_i>.
33883388
[5 6 7 8 9]
33893389
[0 1 2 3 4]
33903390

3391+
See also L</whichND_both> for the n-dimensional version.
3392+
33913393
=cut
33923394

33933395
EOD
@@ -3727,7 +3729,7 @@ sub PDL::whereND :lvalue {
37273729

37283730
EOD
37293731

3730-
pp_add_exported("", 'whichND');
3732+
pp_add_exported("", 'whichND whichND_both');
37313733
pp_addpm(<<'EOD');
37323734
=head2 whichND
37333735

@@ -3825,6 +3827,53 @@ sub PDL::whichND {
38253827
return $mask ? pdl(indx,0) : PDL->new_from_specification(indx,0) if !$ndims;
38263828
_one2nd($mask, $mask->flat->which->dummy(0,$ndims)->sever);
38273829
}
3830+
3831+
=head2 whichND_both
3832+
3833+
=for ref
3834+
3835+
Return the coordinates of non-zero values in a mask.
3836+
3837+
=for usage
3838+
3839+
Like L</which_both>, but returns the N-dimensional coordinates (like
3840+
L</whichND>) of the nonzero, zero values in the mask PDL. The
3841+
returned values arrive as an array-of-vectors suitable for use in
3842+
L<indexND|PDL::Slices/indexND> or L<range|PDL::Slices/range>.
3843+
Added in 2.099.
3844+
3845+
($nonzero_coords, $zero_coords) = whichND_both($mask);
3846+
3847+
SEE ALSO:
3848+
3849+
L</which> finds coordinates of nonzero values in a 1-D mask.
3850+
3851+
L</where> extracts values from a data PDL that are associated
3852+
with nonzero values in a mask PDL.
3853+
3854+
L<PDL::Slices/indexND> can be fed the coordinates to return the values.
3855+
3856+
=for example
3857+
3858+
pdl> $s=sequence(10,10,3,4)
3859+
pdl> ($x, $y, $z, $w)=whichND($s == 203); p $x, $y, $z, $w
3860+
[3] [0] [2] [0]
3861+
pdl> print $s->at(list(cat($x,$y,$z,$w)))
3862+
203
3863+
3864+
=cut
3865+
3866+
*whichND_both = \&PDL::whichND_both;
3867+
sub PDL::whichND_both {
3868+
my $mask = PDL->topdl(shift);
3869+
return ((PDL->new_from_specification(indx,$mask->ndims,0))x2) if !$mask->nelem;
3870+
my $ndims = $mask->getndims;
3871+
if (!$ndims) {
3872+
my ($t, $f) = (pdl(indx,0), PDL->new_from_specification(indx,0));
3873+
return $mask ? ($t,$f) : ($f,$t);
3874+
}
3875+
map _one2nd($mask, $_->dummy(0,$ndims)->sever), $mask->flat->which_both;
3876+
}
38283877
EOD
38293878

38303879
#

t/primitive-selector.t

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ subtest 'which' => sub {
106106
is_pdl $zero, pdl(indx, 3, 5), 'zero indices';
107107
};
108108

109+
subtest 'whichND_both' => sub {
110+
my ( $nonzero, $zero ) = whichND_both(PDL::MatrixOps::identity(2));
111+
is_pdl $nonzero, indx('0 0; 1 1'), 'nonzero indices';
112+
is_pdl $zero, indx('1 0; 0 1'), 'zero indices';
113+
};
114+
109115
subtest 'whichover' => sub {
110116
my $a = pdl q[3 4 6 3 2 3 5 6 1 7];
111117
my $b = $a->uniq;

0 commit comments

Comments
 (0)