File Coverage

blib/lib/Math/Gauss.pm
Criterion Covered Total %
statement 44 44 100.0
branch 22 24 91.6
condition 3 3 100.0
subroutine 7 7 100.0
pod 0 3 0.0
total 76 81 93.8


line stmt bran cond sub pod time code
1             package Math::Gauss;
2              
3 1     1   32968 use 5.010000;
  1         4  
  1         40  
4 1     1   6 use strict;
  1         2  
  1         34  
5 1     1   5 use warnings;
  1         7  
  1         43  
6 1     1   5 use Carp;
  1         2  
  1         1186  
7              
8             require Exporter;
9             our @ISA = qw( Exporter );
10             our %EXPORT_TAGS = ( 'all' => [qw( pdf cdf inv_cdf )] );
11             Exporter::export_ok_tags( 'all' );
12              
13             our $VERSION = '0.01';
14              
15             my $SQRT2PI = 2.506628274631;
16              
17             sub pdf {
18 978505     978505 0 1345239 my ( $x, $m, $s ) = ( 0, 0, 1 );
19 978505 50       2058782 $x = shift if @_;
20 978505 100       1747392 $m = shift if @_;
21 978505 100       1813047 $s = shift if @_;
22              
23 978505 100       1748332 if( $s <= 0 ) {
24 1         239 croak( "Can't evaluate Math::Gauss:pdf for \$s=$s not strictly positive" );
25             }
26              
27 978504         1276920 my $z = ($x-$m)/$s;
28              
29 978504         3375023 return exp(-0.5*$z*$z)/($SQRT2PI*$s);
30             }
31              
32             sub cdf {
33 489253     489253 0 614823 my ( $x, $m, $s ) = ( 0, 0, 1 );
34 489253 50       928922 $x = shift if @_;
35 489253 100       841582 $m = shift if @_;
36 489253 100       800734 $s = shift if @_;
37              
38             # Abramowitz & Stegun, 26.2.17
39             # absolute error less than 7.5e-8 for all x
40              
41 489253 100       855826 if( $s <= 0 ) {
42 1         167 croak( "Can't evaluate Math::Gauss:cdf for \$s=$s not strictly positive" );
43             }
44              
45 489252         647240 my $z = ($x-$m)/$s;
46              
47 489252         687944 my $t = 1.0/(1.0 + 0.2316419*abs($z));
48 489252         852377 my $y = $t*(0.319381530
49             + $t*(-0.356563782
50             + $t*(1.781477937
51             + $t*(-1.821255978
52             + $t*1.330274429 ))));
53 489252 100       771428 if( $z > 0 ) {
54 244015         372949 return 1.0 - pdf( $z )*$y;
55             } else {
56 245237         379667 return pdf( $z )*$y;
57             }
58             }
59              
60             sub inv_cdf {
61 32     32 0 15995 my ( $x ) = @_;
62              
63 32 100 100     195 if( $x<=0.0 || $x>=1.0 ) {
64 4         556 croak( "Can't evaluate Math::Gauss::inv_cdf for \$x=$x outside ]0,1[" );
65             }
66              
67             # Abramowitz & Stegun, 26.2.23
68             # absolute error less than 4.5e-4 for all x
69              
70 28         29 my $t;
71 28 100       50 if( $x < 0.5 ) {
72 13         53 $t = sqrt( -2.0*log($x) );
73             } else {
74 15         48 $t = sqrt( -2.0*log(1.0 - $x) );
75             }
76              
77 28         55 my $y = (2.515517 + $t*(0.802853 + $t*0.010328));
78 28         102 $y /= 1.0 + $t*(1.432788 + $t*(0.189269 + $t*0.001308));
79              
80 28 100       53 if( $x<0.5 ) {
81 13         45 return ( $y - $t );
82             } else {
83 15         59 return ( $t - $y );
84             }
85             }
86              
87             1;
88             __END__