File Coverage

blib/lib/Math/Telephony/ErlangB.pm
Criterion Covered Total %
statement 67 67 100.0
branch 28 28 100.0
condition 45 47 95.7
subroutine 16 16 100.0
pod 4 4 100.0
total 160 162 98.7


line stmt bran cond sub pod time code
1             package Math::Telephony::ErlangB;
2              
3 3     3   85892 use version; our $VERSION = qv('1.0.2');
  3         6745  
  3         15  
4              
5 3     3   225 use warnings;
  3         6  
  3         86  
6 3     3   14 use strict;
  3         12  
  3         68  
7 3     3   14 use Carp;
  3         5  
  3         425  
8 3     3   2573 use English qw( -no_match_vars );
  3         12658  
  3         18  
9              
10 3     3   1314 use base 'Exporter';
  3         6  
  3         1324  
11             our %EXPORT_TAGS =
12             ('all' => [qw( blocking_probability gos servers traffic )]);
13             our @EXPORT_OK = (@{$EXPORT_TAGS{'all'}});
14             our @EXPORT = qw();
15              
16             # Module implementation here
17              
18             # Workhorse functions, no check on input value is done!
19             sub _blocking_probability {
20 305861     305861   405052 my ($traffic, $servers) = @_;
21 305861         305329 my $gos = 1;
22 305861         470523 for my $m (1 .. $servers) {
23 41978597         39595203 my $tmp = $gos * $traffic;
24 41978597         49906324 $gos = $tmp / ($m + $tmp);
25             }
26 305861         1063217 return $gos;
27             } ## end sub _blocking_probability
28              
29             sub _generic_servers {
30 6023     6023   10059 my $cost = shift;
31              
32             # Exponential "backoff"
33 6023         9411 my $servers = 1;
34 6023         13207 $servers *= 2 while ($cost->($servers) > 0);
35 6023 100       15127 return $servers if ($servers <= 2);
36              
37             # Binary search
38 5981         14988 my ($minservers, $maxservers) = ($servers / 2, $servers);
39 5981         20017 while ($maxservers - $minservers > 1) {
40 37962         53326 $servers = int(($maxservers + $minservers) / 2);
41 37962 100       67304 if ($cost->($servers) > 0) {
42 17681         53807 $minservers = $servers;
43             }
44             else {
45 20281         54889 $maxservers = $servers;
46             }
47             } ## end while ($maxservers - $minservers...
48 5981         118552 return $maxservers;
49             } ## end sub _generic_servers
50              
51             sub _generic_traffic {
52 6023     6023   10917 my ($cond, $prec, $hint) = @_;
53              
54             # Establish some upper limit
55 6023   50     16291 my ($inftraffic, $suptraffic) = (0, $hint || 1);
56 6023         13177 while ($cond->($suptraffic)) {
57 899         1790 $inftraffic = $suptraffic;
58 899         1961 $suptraffic *= 2;
59             }
60              
61             # Binary search
62 6023         20349 while (($suptraffic - $inftraffic) / $suptraffic > $prec) {
63 204967         262817 my $traffic = ($suptraffic + $inftraffic) / 2;
64 204967 100       365999 if ($cond->($traffic)) {
65 105175         286863 $inftraffic = $traffic;
66             }
67             else {
68 99792         287616 $suptraffic = $traffic;
69             }
70             } ## end while (($suptraffic - $inftraffic...
71 6023         95029 return $inftraffic;
72             } ## end sub _generic_traffic
73              
74             our $default_precision;
75              
76             BEGIN { # Ok, a little overkill to use a BEGIN block...
77 3     3   1043 $default_precision = 0.001;
78             }
79              
80             sub blocking_probability {
81 6063     6063 1 16451 my ($traffic, $servers) = @_;
82              
83             return undef
84 6063 100 100     92061 unless defined($traffic)
      100        
      100        
      100        
85             && ($traffic >= 0)
86             && defined($servers)
87             && ($servers >= 0)
88             && (int($servers) == $servers);
89 6033 100       17344 return 0 unless $traffic > 0;
90 6028 100       11758 return 1 unless $servers > 0;
91              
92 6023         11999 return _blocking_probability($traffic, $servers);
93             } ## end sub blocking_probability
94              
95 6063     6063 1 3723874 sub gos { return blocking_probability(@_) }
96              
97             sub servers {
98 6063     6063 1 66025 my ($traffic, $gos) = @_;
99              
100             return undef
101 6063 100 100     83258 unless defined($traffic)
      100        
      100        
      100        
102             && ($traffic >= 0)
103             && defined($gos)
104             && ($gos >= 0)
105             && ($gos <= 1);
106 6033 100 66     30113 return 0 unless ($traffic > 0 && $gos < 1);
107 6028 100       15028 return undef unless ($gos > 0);
108              
109             return _generic_servers(
110 6023     87949   32648 sub { _blocking_probability($traffic, $_[0]) > $gos });
  87949         156689  
111             } ## end sub servers
112              
113             sub traffic {
114 6075     6075 1 41675 my ($servers, $gos, $prec) = @_;
115              
116             return undef
117 6075 100 100     87926 unless defined($servers)
      100        
      100        
      100        
      100        
118             && ($servers >= 0)
119             && (int($servers) == $servers)
120             && defined($gos)
121             && ($gos >= 0)
122             && ($gos <= 1);
123 6038 100 100     26305 return 0 unless ($servers > 0 && $gos > 0);
124 6028 100       12530 return undef unless ($gos < 1);
125              
126 6024 100       11283 $prec = $default_precision unless defined $prec;
127 6024 100       12330 return undef unless ($prec > 0);
128              
129             return _generic_traffic(
130 211889     211889   367851 sub { _blocking_probability($_[0], $servers) < $gos },
131 6023         32565 $prec, $servers);
132             } ## end sub traffic
133              
134             1; # Magic true value required at end of module
135             __END__