File Coverage

blib/lib/Math/Random/Cauchy.pm
Criterion Covered Total %
statement 12 44 27.2
branch 0 12 0.0
condition 0 3 0.0
subroutine 4 7 57.1
pod 2 2 100.0
total 18 68 26.4


line stmt bran cond sub pod time code
1             package Math::Random::Cauchy;
2              
3 1     1   30472 use 5.006;
  1         5  
  1         39  
4 1     1   6 use strict;
  1         1  
  1         47  
5 1     1   6 use warnings;
  1         1  
  1         46  
6              
7             our $VERSION = '0.02';
8              
9 1     1   6 use Carp qw/croak/;
  1         1  
  1         488  
10              
11             =head1 NAME
12              
13             Math::Random::Cauchy - Random numbers following a Cauchy PDF
14              
15             =head1 SYNOPSIS
16              
17             use Math::Random::Cauchy;
18             my $cauchy = Math::Random::Cauchy->new(
19             fwhm => 1, # the width (full width, half maximum), default==1
20             middle => 5, # the expectation value, default==0
21             random => 'rand', # use Perl's builtin (default)
22             );
23            
24             foreach (1..100) {
25             my $rnd = $cauchy->rand();
26             # ...
27             }
28            
29             # Use Math::Random::MT instead of bultin rand()
30             use Math::Random::MT;
31             my $mt = Math::Random::Mt->new($seed);
32             $cauchy = Math::Random::Cauchy->new(
33             random => sub { $mt->rand() };
34             );
35              
36             =head1 DESCRIPTION
37              
38             This module transforms uniformly spaced random numbers into random
39             numbers that follow the Cauchy Probability Density Function (I).
40              
41             A more general transformation method is implemented in
42             L.
43              
44             The algorithm is from Blobel et al as quoted in the I section
45             below.
46              
47             =head1 METHODS
48              
49             =cut
50              
51             =head2 new
52              
53             Creates a new random number generator. Takes named arguments.
54              
55             Optional parameters:
56              
57             random: The random number generator. Defaults to using Perl's
58             rand() function. May be set to either 'rand' for the
59             default or a subroutine reference for custom random
60             number generators. Expected to return one or more(!)
61             random numbers per call.
62             fwhm: Full width, half maximum. Defaults to 1.
63             middle: Expectation value for x. Defaults to 0.
64              
65             =cut
66              
67             sub _dor {
68 0     0     foreach (@_) {
69 0 0         return $_ if defined $_;
70             }
71 0           return();
72             }
73              
74             sub new {
75 0     0 1   my $proto = shift;
76 0   0       my $class = ref($proto)||$proto;
77              
78 0           my %args = @_;
79              
80             # Argument checking
81 0           $args{fwhm} = _dor($args{fwhm}, 1);
82 0           $args{middle} = _dor($args{middle}, 1);
83 0 0         if ($args{fwhm} <= 0) {
84 0           croak("'fwhm' must be positive!");
85             }
86 0           $args{random} = _dor($args{random}, 'rand');
87 0 0         if (not ref($args{random}) eq 'CODE') {
88 0 0         croak("'random' parameter must be a CODE reference or 'rand'")
89             if not $args{random} eq 'rand';
90             }
91              
92 0           my $self = {
93             fwhm => $args{fwhm},
94             middle => $args{middle},
95             random => $args{random},
96             cache => [],
97             };
98              
99 0           bless $self => $class;
100              
101 0           return $self;
102             }
103              
104             =head2 rand
105              
106             Returns the next random number of Cauchy PDF.
107              
108             =cut
109              
110             sub rand {
111 0     0 1   my $self = shift;
112 0           my $rnd = $self->{random};
113 0           my $cache = $self->{cache};
114              
115 0           my $x;
116 0           while (not defined $x) {
117 0           while (@$cache < 2) {
118 0 0         if (not ref $rnd) {
119 0           push @$cache, rand();
120             }
121             else {
122 0           push @$cache, $rnd->();
123             }
124             }
125            
126 0           my ($u1, $u2) = (shift(@$cache), shift(@$cache));
127 0           my ($v1, $v2) = (2*$u1-1, 2*$u2-1);
128 0           my $r = $v1**2 + $v2**2;
129 0 0         next if $r > 1;
130 0           $x = 0.5*$v1/$v2;
131             }
132 0           $x = $self->{middle} + $x*$self->{fwhm};
133 0           return $x;
134             }
135              
136             1;
137             __END__