File Coverage

blib/lib/Math/Counting.pm
Criterion Covered Total %
statement 66 66 100.0
branch 10 10 100.0
condition 17 21 80.9
subroutine 12 12 100.0
pod 7 7 100.0
total 112 116 96.5


line stmt bran cond sub pod time code
1             package Math::Counting;
2             our $AUTHORITY = 'cpan:GENE';
3             # ABSTRACT: Combinatorial counting operations
4              
5             our $VERSION = '0.1305';
6              
7 3     3   3160 use strict;
  3         7  
  3         103  
8 3     3   20 use warnings;
  3         5  
  3         125  
9              
10             # Export either "student" or "engineering" methods.
11 3     3   2175 use parent qw(Exporter);
  3         1008  
  3         22  
12             our %EXPORT_TAGS = (
13             student => [qw( factorial permutation combination )],
14             big => [qw( bfact bperm bcomb bderange )],
15             );
16             our @EXPORT_OK = qw(
17             factorial permutation combination
18             bfact bperm bcomb
19             bderange
20             );
21             our @EXPORT = ();
22              
23             # Try to use a math processor.
24 3     3   4865 use Math::BigFloat try => 'GMP,Pari'; # Used for derangement computation only.
  3         68822  
  3         18  
25 3     3   135549 use Math::BigInt try => 'GMP,Pari';
  3         9  
  3         17  
26              
27              
28             sub factorial {
29 8     8 1 3111 my $n = shift;
30 8 100 100     71 return unless defined $n && $n =~ /^\d+$/;
31 6         7 my $product = 1;
32 6         20 while( $n > 0 ) {
33 243         452 $product *= $n--;
34             }
35 6         40 return $product;
36             }
37              
38              
39             sub bfact {
40 7     7 1 3542 my $n = shift;
41 7         25 $n = Math::BigInt->new($n);
42 7         337 return $n->bfac;
43             }
44              
45              
46             sub permutation {
47 11     11 1 3739 my( $n, $k ) = @_;
48 11 100 66     137 return unless defined $n && $n =~ /^\d+$/ && defined $k && $k =~ /^\d+$/;
      66        
      100        
49 8         9 my $product = 1;
50 8         20 while( $k > 0 ) {
51 140         159 $product *= $n--;
52 140         250 $k--;
53             }
54 8         48 return $product;
55             }
56              
57              
58             sub bperm {
59 22     22 1 15171 my( $n, $k, $r ) = @_;
60 22         72 $n = Math::BigInt->new($n);
61 22         1011 $k = Math::BigInt->new($k);
62             # With repetitions?
63 22 100       868 if ($r) {
64 11         35 return $n->bpow($k);
65             }
66             else {
67 11         29 $k = $n - $k;
68 11         1888 return $n->bfac / $k->bfac;
69             }
70             }
71              
72              
73             sub bderange {
74 7     7 1 6349 my $n = shift;
75 7         34 my $mone = Math::BigFloat->bone('-'); # -1
76 7         317 my $s = Math::BigFloat->bzero;
77 7         189 for ( 0 .. $n ) {
78 59         36200 my $i = Math::BigFloat->new($_);
79 59         4158 my $m = $mone->copy;
80 59         1063 my $j = $m->bpow($i);
81 59         7387 my $x = $i->copy;
82 59         1005 my $f = $x->bfac;
83 59         8416 $s += $j / $f;
84             }
85 7         4337 $n = Math::BigFloat->new($n);
86 7         562 return $n->bfac * $s;
87             }
88              
89              
90             sub combination {
91 11     11 1 4968 my( $n, $k ) = @_;
92 11 100 66     165 return unless defined $n && $n =~ /^\d+$/ && defined $k && $k =~ /^\d+$/;
      66        
      100        
93 8         17 my $product = 1;
94 8         21 while( $k > 0 ) {
95 140         228 $product *= $n--;
96 140         333 $product /= $k--;
97             }
98 8         43 return $product;
99             }
100              
101              
102             sub bcomb {
103 22     22 1 22232 my( $n, $k, $r ) = @_;
104 22         93 $n = Math::BigInt->new($n);
105 22         1225 $k = Math::BigInt->new($k);
106             # With repetitions?
107 22 100       1090 if ($r) {
108 11         39 my $c1 = $n + $k - 1;
109 11         2822 my $c2 = $n - 1;
110 11         1900 return $c1->bfac / ($k->bfac * $c2->bfac);
111             }
112             else {
113 11         43 my $c1 = $n - $k;
114 11         1174 return $n->bfac / ($k->bfac * $c1->bfac);
115             }
116             }
117              
118             1;
119              
120             __END__