File Coverage

blib/lib/Math/GrahamFunction/SqFacts.pm
Criterion Covered Total %
statement 78 80 97.5
branch 14 16 87.5
condition 7 7 100.0
subroutine 18 18 100.0
pod 8 8 100.0
total 125 129 96.9


line stmt bran cond sub pod time code
1             package Math::GrahamFunction::SqFacts;
2             $Math::GrahamFunction::SqFacts::VERSION = '0.02002';
3 2     2   15 use strict;
  2         4  
  2         70  
4 2     2   14 use warnings;
  2         5  
  2         79  
5              
6              
7 2     2   22 use parent qw(Math::GrahamFunction::Object);
  2         24  
  2         15  
8              
9 2     2   127 use List::Util ();
  2         6  
  2         1503  
10             __PACKAGE__->mk_accessors(qw(n factors));
11              
12             sub _initialize
13             {
14 1771     1771   2652 my $self = shift;
15 1771         2621 my $args = shift;
16              
17 1771 100       4053 if ($args->{n})
    50          
18             {
19 844         2314 $self->n($args->{n});
20              
21 844         8697 $self->_calc_sq_factors();
22             }
23             elsif ($args->{factors})
24             {
25 927         2036 $self->factors($args->{factors});
26             }
27             else
28             {
29 0         0 die "factors or n must be supplied.";
30             }
31              
32 1771         10523 return 0;
33             }
34              
35              
36             sub clone
37             {
38 182     182 1 964 my $self = shift;
39 182         286 return __PACKAGE__->new({'factors' => [@{$self->factors()}]});
  182         341  
40             }
41              
42             sub _calc_sq_factors
43             {
44 844     844   1267 my $self = shift;
45              
46 844         1581 $self->factors($self->_get_sq_facts($self->n()));
47              
48 844         8133 return 0;
49             }
50              
51             my %gsf_cache = (1 => []);
52              
53             sub _get_sq_facts
54             {
55 973     973   7987 my $self = shift;
56 973         1459 my $n = shift;
57              
58 973 100       2631 if (exists($gsf_cache{$n}))
59             {
60 844         2637 return $gsf_cache{$n};
61             }
62              
63 129   100     451 my $start_from = shift || 2;
64              
65 129         238 for(my $p=$start_from; ;$p++)
66             {
67 1720 100       3062 if ($n % $p == 0)
68             {
69             # This function is recursive to make better use of the Memoization
70             # feature.
71 129         371 my $division_factors = $self->_get_sq_facts(($n / $p), $p);
72 129 100 100     498 if (@$division_factors && ($division_factors->[0] == $p))
73             {
74 29         64 return ($gsf_cache{$n} = [ @{$division_factors}[1 .. $#$division_factors] ]);
  29         158  
75             }
76             else
77             {
78 100         590 return ($gsf_cache{$n} = [ $p, @$division_factors ]);
79             }
80             }
81             }
82             }
83              
84             # Removed because it is too slow - we now use our own custom memoization (
85             # or perhaps it is just called caching)
86             # memoize('get_squaring_factors', 'NORMALIZER' => sub { return $_[0]; });
87              
88             # This function multiplies the squaring factors of $n and $m to receive
89             # the squaring factors of ($n*$m)
90              
91             # OOP-Wise, it should be a multi-method, but since we don't inherit this
92             # object it's all-right.
93              
94              
95             sub mult_by
96             {
97 2042     2042 1 30567 my $n_ref = shift;
98 2042         2895 my $m_ref = shift;
99              
100 2042         2764 my @n = @{$n_ref->factors()};
  2042         3811  
101             my @m =
102 2042         18945 eval {
103 2042         2760 @{$m_ref->factors()};
  2042         3615  
104             };
105 2042 50       20508 if ($@)
106             {
107 0         0 print "Hello\n";
108             }
109              
110 2042         2917 my @ret = ();
111              
112 2042   100     6658 while (scalar(@n) && scalar(@m))
113             {
114 4255 100       8703 if ($n[0] == $m[0])
    100          
115             {
116 1836         2825 shift(@n);
117 1836         4555 shift(@m);
118             }
119             elsif ($n[0] < $m[0])
120             {
121 1315         4146 push @ret, shift(@n);
122             }
123             else
124             {
125 1104         3814 push @ret, shift(@m);
126             }
127             }
128 2042         3594 push @ret, @n, @m;
129              
130 2042         5328 $n_ref->factors(\@ret);
131              
132             # 0 for success
133 2042         21291 return 0;
134             }
135              
136              
137             sub mult
138             {
139 90     90 1 1515 my $n = shift;
140 90         128 my $m = shift;
141              
142 90         182 my $result = $n->clone();
143 90         284 $result->mult_by($m);
144 90         199 return $result;
145             }
146              
147              
148             sub is_square
149             {
150 1364     1364 1 12269 my $self = shift;
151 1364         2017 return (scalar(@{$self->factors()}) == 0);
  1364         2530  
152             }
153              
154              
155             sub exists
156             {
157 1949     1949 1 16867 my ($self, $factor) = @_;
158              
159 1949     2940   5348 return defined(List::Util::first { $_ == $factor } @{$self->factors()});
  2940         25269  
  1949         3892  
160             }
161              
162              
163             sub last
164             {
165 90     90 1 824 my $self = shift;
166              
167 90         197 return $self->factors()->[-1];
168             }
169              
170 2     2   17 use vars qw($a $b);
  2         11  
  2         345  
171              
172              
173             sub product
174             {
175 90     90 1 143 my $self = shift;
176              
177 90     43   269 return (List::Util::reduce { $a * $b } @{$self->factors()});
  43         432  
  90         184  
178             }
179              
180              
181             sub first
182             {
183 600     600 1 5318 my $self = shift;
184              
185 600         1118 return $self->factors()->[0];
186             }
187              
188              
189             1;
190              
191             __END__