Skip to content

Commit 643918b

Browse files
committed
Revert "simplify some calculations" as causes numerical problems - fix #34
This reverts commit 826ec94.
1 parent b5e20d4 commit 643918b

File tree

3 files changed

+11
-4
lines changed

3 files changed

+11
-4
lines changed

Changes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
- fix recent change that allowed negative variance and standard deviation (#34) - thanks @shawnlaffan for report
2+
13
0.854 2025-02-25
24
- fix anova_rptd problem depending on grouping of IVs (part of RT#97925)
35
- do all plotting with PDL::Graphics::Simple

lib/PDL/Stats/Basic.pd

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pp_def('stdv',
5959
a2 += $a() * $a();
6060
%}
6161
if (N < 1) { $SETBAD(b()); continue; }
62-
$b() = sqrt( (a2 - sa*sa/N) / N );
62+
$b() = sqrt( a2 / N - (sa/N)*(sa/N) );
6363
',
6464
Doc => 'Sample standard deviation.',
6565
);
@@ -77,7 +77,7 @@ pp_def('stdv_unbiased',
7777
a2 += $a() * $a();
7878
%}
7979
if (N < 2) { $SETBAD(b()); continue; }
80-
$b() = pow( (a2 - sa*sa/N) / (N-1), .5 );
80+
$b() = pow( a2/(N-1) - sa*sa/(N*(N-1)), .5 );
8181
',
8282
Doc => 'Unbiased estimate of population standard deviation.',
8383
);
@@ -95,7 +95,7 @@ pp_def('var',
9595
a2 += $a() * $a();
9696
%}
9797
if (N < 1) { $SETBAD(b()); continue; }
98-
$b() = (a2 - sa*sa/N) / N;
98+
$b() = a2 / N - sa*sa/(N*N);
9999
',
100100
Doc => 'Sample variance.',
101101
);
@@ -275,7 +275,7 @@ pp_def('cov',
275275
sb += $b();
276276
%}
277277
if (N < 1) { $SETBAD(c()); continue; }
278-
$c() = (ab - sa*sb/N) / N;
278+
$c() = ab / N - (sa/N) * (sb/N);
279279
',
280280
Doc => 'Sample covariance. see B<corr> for ways to call',
281281
);

t/glm.t

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ is_pdl pdl('BAD 1 2 3 4')->fill_m, pdl('2.5 1 2 3 4'), "fill_m replaces bad valu
1111
{
1212
my $stdv = pdl('BAD 1 2 3 4')->fill_rand->stdv;
1313
ok PDL::Core::approx( $stdv, 1.01980390271856 ) || PDL::Core::approx( $stdv, 1.16619037896906 ), "fill_rand replaces bad values with random sample of good values from same variable";
14+
my $x = pdl [(0.001) x 6];
15+
my $var = $x->var;
16+
ok $var >= 0, 'var >= 0' or diag "var = $var";
17+
$stdv = $x->stdv;
18+
ok $stdv >= 0, 'stdv >= 0' or diag "stdv = $stdv";
1419
}
1520

1621
my $a = sequence 5;

0 commit comments

Comments
 (0)