From 13dc82ecce53d97eab1c83d1f1eed050030efd18 Mon Sep 17 00:00:00 2001 From: Boyd Duffee Date: Sat, 9 May 2026 12:01:53 +0100 Subject: [PATCH] Fix acf and acvf default handling Moved PMCode logic to Pars with defaults and added subtest --- lib/PDL/Stats/TS.pd | 26 ++++++-------------------- t/ts.t | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/lib/PDL/Stats/TS.pd b/lib/PDL/Stats/TS.pd index 3bb1386..82ce1d7 100644 --- a/lib/PDL/Stats/TS.pd +++ b/lib/PDL/Stats/TS.pd @@ -48,8 +48,9 @@ pp_addhdr(' ); pp_def('acf', - Pars => 'x(t); [o]r(h)', - OtherPars => 'IV lag=>h', + Pars => 'x(t); [o]r(h=CALC($COMP(lag) < 0 ? $SIZE(t) : $COMP(lag) + 1))', + OtherPars => 'IV lag', + OtherParsDefaults => { lag => -1 }, GenericTypes => $F, Code => ' $GENERIC(x) s, s2, m, cov0, covh; @@ -75,14 +76,6 @@ loop (h) %{ } %} ', - PMCode => pp_line_numbers(__LINE__, <<'EOF'), -sub PDL::acf { - my ($self, $h) = @_; - $h ||= $self->dim(0) - 1; - PDL::_acf_int($self, my $r = PDL->null, $h+1); - $r; -} -EOF Doc => <<'EOD', =for ref @@ -104,8 +97,9 @@ EOD ); pp_def('acvf', - Pars => 'x(t); [o]v(h)', - OtherPars => 'IV lag=>h;', + Pars => 'x(t); [o]v(h=CALC($COMP(lag) < 0 ? $SIZE(t) : $COMP(lag) + 1))', + OtherPars => 'IV lag', + OtherParsDefaults => { lag => -1 }, GenericTypes => $F, Code => ' $GENERIC(x) s, s2, m, covh; @@ -130,14 +124,6 @@ loop (h) %{ } %} ', - PMCode => pp_line_numbers(__LINE__, <<'EOF'), -sub PDL::acvf { - my ($self, $h) = @_; - $h ||= $self->dim(0) - 1; - PDL::_acvf_int($self, my $v = PDL->null, $h+1); - $v; -} -EOF Doc => <<'EOD', =for ref diff --git a/t/ts.t b/t/ts.t index d3fc97a..5a64881 100644 --- a/t/ts.t +++ b/t/ts.t @@ -58,4 +58,25 @@ use Test::PDL; is_pdl $ms, $ans_ms, 'season_m ms'; } +subtest 'acf and acvf with lags' => sub { + my $a = sequence 10; + my $m = sequence 10,2; + my $acvf = pdl '[82.5 57.75 34 12.25 -6.5 -21.25 -31 -34.75 -31.5 -20.25]'; + my $acf = $acvf / $acvf->at(0); + + is_pdl $a->acvf(), $acvf, "calculate autocovariance with no arguments on $a"; + + is_pdl $a->acvf(4), $acvf->slice('0:4'), "calculate autocovariance with 4 lags on $a"; + is_pdl $a->acvf(0), $acvf->slice('0:0'), "calculate autocovariance with 0 lag on $a"; + is_pdl $a->acvf(5) / $a->acvf(0), $a->acf(5), "calculate autocorrelation from autocovariance on $a"; + is_pdl $a->acvf(14), $acvf->append([0,0,0,0,0]), "autocovariance called with more lags than values"; + + is_pdl $a->acf(), $acf, "calculate autocorrelation with no arguments on $a"; + is_pdl $a->acf(0), pdl('[1]'), 'first value of the autocorrelation function is always 1'; + is_pdl $a->acf(5), $acf->slice('0:5'), 'autocorrelation function with 5 lags'; + + # autocorrelation on higher order pdls is a collection of 1D arrays + is_pdl $m->acvf(4), $acvf->slice('0:4')->dummy(1,2), "acvf is the same for both rows of sequence(10,2)"; +}; + done_testing;