File: CDF.pd

package info (click to toggle)
libpdl-gsl-perl 2.101-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 600 kB
  • sloc: perl: 1,587; ansic: 202; makefile: 9
file content (181 lines) | stat: -rw-r--r-- 10,163 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
use strict;
use warnings;

our $VERSION = '2.096';

pp_addpm({At=>'Top'},<<'EOD');

use strict;
use warnings;

=head1 NAME

PDL::GSL::CDF - PDL interface to GSL Cumulative Distribution Functions

=head1 DESCRIPTION

This is an interface to the Cumulative Distribution Function package present in the GNU Scientific Library.

Let us have a continuous random number distributions are defined by a probability density function C<p(x)>.

The cumulative distribution function for the lower tail C<P(x)> is defined by the integral of C<p(x)>, and
gives the probability of a variate taking a value less than C<x>. These functions are named B<cdf_NNNNNNN_P()>.

The cumulative distribution function for the upper tail C<Q(x)> is defined by the integral of C<p(x)>, and
gives the probability of a variate taking a value greater than C<x>. These functions are named B<cdf_NNNNNNN_Q()>.

The upper and lower cumulative distribution functions are related by C<P(x) + Q(x) = 1> and
satisfy C<0 E<lt>= P(x) E<lt>= 1> and C<0 E<lt>= Q(x) E<lt>= 1>.

The inverse cumulative distributions, C<x = Pinv(P)> and C<x = Qinv(Q)> give the values of C<x> which correspond
to a specific value of C<P> or C<Q>. They can be used to find confidence limits from probability values.
These functions are named B<cdf_NNNNNNN_Pinv()> and B<cdf_NNNNNNN_Qinv()>.

For discrete distributions the probability of sampling the integer value C<k> is given by C<p(k)>, where
C<sum_k p(k) = 1>. The cumulative distribution for the lower tail C<P(k)> of a discrete distribution is
defined as, where the sum is over the allowed range of the distribution less than or equal to C<k>.

The cumulative distribution for the upper tail of a discrete distribution C<Q(k)> is defined as giving the sum
of probabilities for all values greater than C<k>. These two definitions satisfy the identity C<P(k) + Q(k) = 1>.

If the range of the distribution is C<1> to C<n> inclusive then C<P(n) = 1>, C<Q(n) = 0>
while C<P(1) = p(1)>, C<Q(1) = 1 - p(1)>.

=head1 SYNOPSIS

    use PDL;
    use PDL::GSL::CDF;

    my $p = gsl_cdf_tdist_P( $t, $df );

    my $t = gsl_cdf_tdist_Pinv( $p, $df );

=cut

EOD

pp_addhdr('
#include <gsl/gsl_cdf.h>
#include <gsl/gsl_errno.h>

static char *funcname;

static void cdf_error_handler(const char *reason, const char *file, int line, int status) {
  char buf[200];
  sprintf(buf,"Error in %s: %s", funcname, gsl_strerror(status));
  barf(buf);
}

');

use Text::ParseWords qw(shellwords);
chomp(my $header = `gsl-config --cflags`);
$header =~ s#\\#/#g; # win32
($header) = map {s/^-I//;$_} grep /^-I/, shellwords $header;
$header .= '/gsl/gsl_cdf.h';
my $h = do { open my $fh, "<", $header or die "$header: $!"; local $/ = undef; <$fh> };
my @functions = $h =~ m/(double\s+gsl_cdf_.+?\)\s*;\s*)\n/xmsg;
my @func_defs;

my %p_type = (
  'double'       => 'double',
  'unsigned int' => 'ulonglong',
);

my %func_desc = (
  gsl_cdf_gaussian          => ['The Gaussian Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the Gaussian distribution with standard deviation I<sigma>.'],
  gsl_cdf_ugaussian         => ['The Unit Gaussian Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the unit Gaussian distribution.'],
  gsl_cdf_exponential       => ['The Exponential Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the exponential distribution with mean I<mu>.'],
  gsl_cdf_laplace           => ['The Laplace Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the Laplace distribution with width I<a>.'],
  gsl_cdf_exppow            => ['The Exponential Power Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) for the exponential power distribution with parameters I<a> and I<b>.'],
  gsl_cdf_cauchy            => ['The Cauchy Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the Cauchy distribution with scale parameter I<a>.'],
  gsl_cdf_rayleigh          => ['The Rayleigh Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the Rayleigh distribution with scale parameter I<sigma>.'],
  gsl_cdf_gamma             => ['The Gamma Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the gamma distribution with parameters I<a> and I<b>.'],
  gsl_cdf_flat              => ['The Flat (Uniform) Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for a uniform distribution from I<a> to I<b>.'],
  gsl_cdf_lognormal         => ['The Lognormal Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the lognormal distribution with parameters I<zeta> and I<sigma>.'],
  gsl_cdf_chisq             => ['The Chi-squared Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the chi-squared distribution with I<nu> degrees of freedom.'],
  gsl_cdf_fdist             => ['The F-distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the F-distribution with I<nu1> and I<nu2> degrees of freedom.'],
  gsl_cdf_tdist             => ['The t-distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the t-distribution with I<nu> degrees of freedom.'],
  gsl_cdf_beta              => ['The Beta Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the beta distribution with parameters I<a> and I<b>.'],
  gsl_cdf_logistic          => ['The Logistic Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the logistic distribution with scale parameter I<a>.'],
  gsl_cdf_pareto            => ['The Pareto Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the Pareto distribution with exponent I<a> and scale I<b>.'],
  gsl_cdf_weibull           => ['The Weibull Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the Weibull distribution with scale I<a> and exponent I<b>.'],
  gsl_cdf_gumbel1           => ['The Type-1 Gumbel Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the Type-1 Gumbel distribution with parameters I<a> and I<b>.'],
  gsl_cdf_gumbel2           => ['The Type-2 Gumbel Distribution', 'These functions compute the cumulative distribution functions P(x), Q(x) and their inverses for the Type-2 Gumbel distribution with parameters I<a> and I<b>.'],
  gsl_cdf_poisson           => ['The Poisson Distribution', 'These functions compute the cumulative distribution functions P(k), Q(k) for the Poisson distribution with parameter I<mu>.'],
  gsl_cdf_binomial          => ['The Binomial Distribution', 'These functions compute the cumulative distribution functions P(k), Q(k) for the binomial distribution with parameters I<p> and I<n>.'],
  gsl_cdf_negative_binomial => ['The Negative Binomial Distribution', 'These functions compute the cumulative distribution functions P(k), Q(k) for the negative binomial distribution with parameters I<p> and I<n>.'],
  gsl_cdf_pascal            => ['The Pascal Distribution', 'These functions compute the cumulative distribution functions P(k), Q(k) for the Pascal distribution with parameters I<p> and I<n>.'],
  gsl_cdf_geometric         => ['The Geometric Distribution', 'These functions compute the cumulative distribution functions P(k), Q(k) for the geometric distribution with parameter I<p>.'],
  gsl_cdf_hypergeometric    => ['The Hypergeometric Distribution', 'These functions compute the cumulative distribution functions P(k), Q(k) for the hypergeometric distribution with parameters I<n1>, I<n2> and I<t>.'],
);

for (@functions) {
  s/\n\s+/ /xmsg;
  s/const //g;
  if (m/^(\w+)\s+(\w+)\s*\(\s*(.+)\s*\)\s*\;$/s) {
    my ($out_type, $function, $pars) = ($1, $2, $3);
    my @pars = split /,/, $pars;
    for (@pars) {
      if (m/^(.+)( \w+)$/) {
        my ($type, $par) = ($1, $2);
        s/^ | $//g for ($type, $par);
        $par = lc $par;
        $_ = [$p_type{$type}, $par];
      }
    }
    push @func_defs, [ $out_type, $function, \@pars ];
  }
}

@func_defs = sort { $a->[1] cmp $b->[1] } @func_defs; # sort by function name

for my $f (@func_defs) {
  my ($out_type, $function, $pars) = @$f;
  my $func_short = join '_', (split '_', $function)[0..2];
  my ($p, $code) = print_ppdef($out_type, $function, @$pars);
  my $desc = delete $func_desc{$func_short};
  pp_addpm(qq{\n=head2 $desc->[0] (${func_short}_*)\n\n$desc->[1]\n\n=cut\n\n}) if $desc;
  pp_def($function,
    HandleBad => 1,
    GenericTypes => ['D'],
    Pars => $p,
    Code => $code,
    Doc  => '',
  );
}

sub print_ppdef {
  my ($out_type, $function, @pars) = @_;
  @pars = map $_->[0] eq 'double' ? [$_->[1]] : $_, @pars;
  my $pars = join ' ', map "@$_();", @pars, ['[o]out'];
  my $code = pp_line_numbers(__LINE__, <<EOF);
gsl_error_handler_t *current_handler;
funcname = "$function";
current_handler = gsl_set_error_handler(cdf_error_handler);
\$out() = $function(@{[join ', ', map "\$$_->[-1]()", @pars]});
gsl_set_error_handler(current_handler);
EOF
  $code =
    "PDL_IF_BAD(if ( !(" . join(' && ', map { "\$ISGOOD($_->[-1]())" } @pars ) . ") ) {" .
    "\$SETBAD(out()); }" .
    'else,) {' . $code . "}\n";
  return ($pars, $code);
}

pp_addpm({At=>'Bot'},<<'EOD');

=head1 AUTHOR

Copyright (C) 2009 Maggie J. Xiong <maggiexyz users.sourceforge.net>

The GSL CDF module was written by J. Stover.

All rights reserved. There is no warranty. You are allowed to redistribute this software / documentation as described in the file COPYING in the PDL distribution.

=cut

EOD

pp_done();