File Coverage

blib/lib/Math/NumSeq.pm
Criterion Covered Total %
statement 77 87 88.5
branch 15 20 75.0
condition 11 22 50.0
subroutine 27 29 93.1
pod 9 16 56.2
total 139 174 79.8


line stmt bran cond sub pod time code
1             # Copyright 2010, 2011, 2012, 2013, 2014 Kevin Ryde
2              
3             # This file is part of Math-NumSeq.
4             #
5             # Math-NumSeq is free software; you can redistribute it and/or modify
6             # it under the terms of the GNU General Public License as published by the
7             # Free Software Foundation; either version 3, or (at your option) any later
8             # version.
9             #
10             # Math-NumSeq is distributed in the hope that it will be useful, but
11             # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12             # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13             # for more details.
14             #
15             # You should have received a copy of the GNU General Public License along
16             # with Math-NumSeq. If not, see .
17              
18              
19             # ($value1,$value2) = $self->ith_pair($i);
20             # Return values for $i and $i+1, possibly undefs.
21             # Same as ($self->ith($i), $self->ith($i+1)) but some classes faster.
22             # SternDiatomic
23             # Fibonacci -- with ith() being sans last bit
24             # ith_pair_from_bits_hightolow()
25             # LucasNumbers -- F,L then last step L,L
26             # ith_FL_from_bits_hightolow()
27              
28             # $value = $seq->value_floor($value)
29             # $value = $seq->value_ceil($value)
30             # $value = $seq->value_next($value)
31             # characteristic('distinct')
32             # characteristic('geometric') geometric progression constant multipler
33             # characteristic('arithmetic') arithmetic progression constant add
34             # characteristic('primitive') no term divisible by any other
35             # characteristic('mult_prev') each term multiple of previous
36              
37             # $seq->i_end last i if finite, and if known ??
38             # characteristic('i_end')
39             # characteristic('i_finite') boolean
40              
41             # ->add ->sub of sequence or constant
42             # ->mul
43             # ->mod($k) of constant
44             # overloads
45             # ->shift
46             # ->inverse some with known ways to calculate
47             # ->is_subset_of
48              
49             # lo,hi i or value
50             # lo_value,hi_value
51              
52             # Sequence::Array from arrayref
53             # Derived::Interleave
54              
55              
56              
57              
58             package Math::NumSeq;
59 63     63   3769 use 5.004;
  63         215  
  63         4407  
60 63     63   445 use strict;
  63         130  
  63         3410  
61              
62 63     63   342 use vars '$VERSION', '@ISA';
  63         171  
  63         11897  
63             $VERSION = 71;
64              
65             # uncomment this to run the ### lines
66             #use Smart::Comments;
67              
68             BEGIN {
69 63 50 33 63   4063 eval "\n#line ".(__LINE__+1)." \"".__FILE__."\"\n" . <<'HERE'
70             # print "attempt Locale::Messages for __\n";
71 63     63   31396 use Locale::Messages ();
  0         0  
  0         0  
72             sub __ { Locale::Messages::dgettext('Math-NumSeq',$_[0]) }
73             1;
74             HERE
75             || eval "\n#line ".(__LINE__+1)." \"".__FILE__."\"\n" . <<'HERE'
76             # print "fallback definition of __\n";
77 746     746   1803342 sub __ { $_[0] };
78             1;
79             HERE
80             || die $@;
81             }
82              
83             # sub name {
84             # my ($self) = @_;
85             # my $name = ref($self) || $self;
86             # $name =~ s/^Math::NumSeq:://;
87             # return $name;
88             # }
89              
90 63     63   354 use constant description => undef;
  63         119  
  63         8689  
91             sub oeis_anum {
92 18     18 1 125 my ($self) = @_;
93 18   100     105 return $self->{'oeis_anum'} || undef;
94             }
95              
96 63     63   345 use constant default_i_start => 1;
  63         137  
  63         12367  
97             sub i_start {
98 3579     3579 1 29559 my ($self) = @_;
99 3579 100       18624 return (defined $self->{'i_start'}
100             ? $self->{'i_start'}
101             : $self->default_i_start);
102             }
103             sub values_min {
104 38     38 1 410 my ($self) = @_;
105 38         161 return $self->{'values_min'};
106             }
107             sub values_max {
108 0     0 1 0 my ($self) = @_;
109 0         0 return $self->{'values_max'};
110             }
111              
112 63     63   367 use constant parameter_info_array => [];
  63         120  
  63         37980  
113             sub parameter_info_list {
114 1017     1017 1 1619 return @{$_[0]->parameter_info_array};
  1017         23749  
115             }
116              
117             # not documented yet
118             my %parameter_info_hash;
119             sub parameter_info_hash {
120 6     6 0 2379 my ($class_or_self) = @_;
121 6   33     50 my $class = (ref $class_or_self || $class_or_self);
122 9         2833 return ($parameter_info_hash{$class}
123 6   100     154 ||= { map { $_->{'name'} => $_ }
124             $class_or_self->parameter_info_list });
125             }
126              
127             # not documented yet
128             sub parameter_default {
129 0     0 0 0 my ($class_or_self, $name) = @_;
130             ### Values parameter_default: @_
131             ### info: $class_or_self->parameter_info_hash->{$name}
132 0         0 my $info;
133 0   0     0 return (($info = $class_or_self->parameter_info_hash->{$name})
134             && $info->{'default'});
135             }
136              
137              
138             # pn1 values +1, -1, 0
139             # permutation
140             # delta
141             # boolean ?
142             sub characteristic {
143 860     860 1 566938 my $self = shift;
144 860         1473 my $type = shift;
145 860 50 33     5500 if (ref $self
146             && (my $href = $self->{'characteristic'})) {
147 0 0       0 if (exists $href->{$type}) {
148 0         0 return $href->{$type};
149             }
150             }
151 860 100       3464 if (my $subr = $self->can("characteristic_${type}")) {
152 552         3913 return $self->$subr (@_);
153             }
154 308         941 return undef;
155             }
156              
157             # default i_start if "increasing"
158             sub characteristic_increasing_from_i {
159 16     16 0 518 my ($self) = @_;
160 16 100       69 return ($self->characteristic('increasing')
161             ? $self->i_start
162             : undef);
163             }
164              
165             # default from the stronger condition "increasing"
166             sub characteristic_non_decreasing {
167 29     29 0 125 my ($self) = @_;
168 29         173 return $self->characteristic('increasing');
169             }
170             sub characteristic_non_decreasing_from_i {
171 17     17 0 42 my ($self) = @_;
172 17 100       66 return ($self->characteristic('non_decreasing')
173             ? $self->i_start
174             : undef);
175             }
176              
177             # default "count" is integer
178             sub characteristic_integer {
179 4     4 0 13 my ($self) = @_;
180 4         156 return $self->characteristic_count;
181             }
182 63     63   400 use constant characteristic_count => undef; # don't know
  63         129  
  63         36224  
183              
184              
185             #------------------------------------------------------------------------------
186              
187             sub new {
188 972     972 1 7448330 my ($class, %self) = @_;
189             ### Sequence new(): $class
190 972         3947 my $self = bless \%self, $class;
191              
192 972         4584 foreach my $pinfo ($self->parameter_info_list) {
193 935         2744 my $pname = $pinfo->{'name'};
194 935 100       4727 if (! defined $self->{$pname}) {
195             ### default: $pname
196 177         1000 $self->{$pname} = $pinfo->{'default'};
197             }
198             }
199 972         5490 $self->rewind;
200 971         5578 return $self;
201             }
202              
203             sub tell_i {
204 456     456 1 5656 my ($self) = @_;
205 456         1642 return $self->{'i'};
206             }
207              
208             sub ith_pair {
209 2722     2722 1 13165 my ($self, $i) = @_;
210 2722         7871 return ($self->ith($i), $self->ith($i+1));
211             }
212              
213             sub can {
214 48678     48678 0 5790359 my ($class, $method) = @_;
215 48678 50 66     141116 if ($method eq 'ith_pair' && ! return $class->can('ith')) {
216 0         0 return undef;
217             }
218 48450         220574 return $class->SUPER::can($method);
219             }
220              
221             #------------------------------------------------------------------------------
222             # shared internals
223              
224             # cf Data::Float, but it might not handle BigFloat
225             sub _is_infinite {
226 236810     236810   312611 my ($x) = @_;
227 236810   66     1787939 return ($x != $x # nan
228             || ($x != 0 && $x == 2*$x)); # inf
229             }
230              
231             # or maybe check for new enough for uv->mpz fix
232             use constant::defer _bigint => sub {
233             # Crib note: don't change the back-end if already loaded
234 14 100       456 unless (Math::BigInt->can('new')) {
235 11         24561 require Math::BigInt;
236 11         473193 eval { Math::BigInt->import (try => 'GMP') };
  11         73  
237             }
238 14         298514 return 'Math::BigInt';
239 63     63   86669 };
  63         60483  
  63         691  
240              
241             sub _to_bigint {
242 1659     1659   10585 my ($n) = @_;
243             # stringize to avoid UV->BigInt bug in Math::BigInt::GMP version 1.37
244 1659         8302 return _bigint()->new("$n");
245             }
246              
247             1;
248             __END__