Skip to content

Commit

Permalink
add Ufunc::diffcentred - #516
Browse files Browse the repository at this point in the history
  • Loading branch information
mohawk2 committed Jan 7, 2025
1 parent 6ea9df7 commit a917b61
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
1 change: 1 addition & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- now an error to upd_data if datasv set to different size from nbytes
- add PDL::readonly method (#516) - thanks @wlmb for suggestion
- rename Ufunc::diffover to Ufunc::numdiff (#516)
- add Ufunc::diffcentred (#516)

2.098 2025-01-03
- fix Windows build problems
Expand Down
32 changes: 32 additions & 0 deletions lib/PDL/Ufunc.pd
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,38 @@ Compare to L</cumusumover>, which acts as the converse of this.
EOF
);

pp_def('diffcentred',
HandleBad => 1,
Pars => 'a(n); [o]o(nminus2=CALC($SIZE(n) - 2))',
GenericTypes => [ppdefs_all],
Code => <<'EOF',
loop(nminus2) %{
PDL_IF_BAD(if ($ISBAD($a(n=>nminus2)) || $ISBAD($a(n=>nminus2+2))) {
$SETBAD(o()); continue;
},)
$o() = ($a(n=>nminus2+2) - $a(n=>nminus2))/2;
%}
EOF
Doc => <<'EOF',
=for ref
Calculates centred differences along a vector's 0th dimension.
Currently takes no account of boundary values, so produces 2 fewer
values than on the input.
By using L<PDL::Slices/xchg> etc. it is possible to use I<any> dimension.
=for usage
print pdl(q[3 4 2 3 2 3 1])->diff2;
# [1 -2 1 -1 1 -2]
EOF
BadDoc => <<'EOF',
A bad value at C<n> means the affected output values at C<n-2>,C<n>
(if in boounds) are set bad.
EOF
);

pp_def('diff2',
HandleBad => 1,
Pars => 'a(n); [o]o(nminus1=CALC($SIZE(n) - 1))',
Expand Down
8 changes: 8 additions & 0 deletions t/ufunc.t
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,14 @@ subtest numdiff => sub {
is_pdl $a, pdl(2, 1, 1, 1, 1), "numdiff inplace";
};

subtest diffcentred => sub {
my $a = sequence(6) + 2;
is_pdl $a->diffcentred, pdl(1, 1, 1, 1), "diffcentred";
is_pdl +($a**2)->diffcentred, pdl('6 8 10 12'), "diffcentred of x^2";
$a->setbadat(2);
is_pdl +($a**2)->diffcentred, pdl('BAD 8 BAD 12'), "diffcentred of x^2 with bad";
};

subtest diff2 => sub {
my $got = pdl('[BAD 2 3 4]')->diff2;
is "$got", "[2 1 1]", 'first bad';
Expand Down

0 comments on commit a917b61

Please sign in to comment.