File Coverage

blib/lib/Math/NumSeq/StarNumbers.pm
Criterion Covered Total %
statement 61 63 96.8
branch 11 12 91.6
condition n/a
subroutine 18 19 94.7
pod 4 4 100.0
total 94 98 95.9


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             package Math::NumSeq::StarNumbers;
19 1     1   1309 use 5.004;
  1         3  
20 1     1   4 use strict;
  1         1  
  1         23  
21 1     1   3 use POSIX 'ceil';
  1         1  
  1         8  
22 1     1   63 use List::Util 'max';
  1         2  
  1         43  
23              
24 1     1   3 use vars '$VERSION','@ISA';
  1         2  
  1         72  
25             $VERSION = 72;
26              
27 1     1   6 use Math::NumSeq;
  1         2  
  1         22  
28 1     1   5 use Math::NumSeq::Base::IterateIth;
  1         1  
  1         38  
29             @ISA = ('Math::NumSeq::Base::IterateIth',
30             'Math::NumSeq');
31              
32             # uncomment this to run the ### lines
33             #use Smart::Comments;
34              
35             # use constant name => Math::NumSeq::__('Star Numbers');
36 1     1   7 use constant description => Math::NumSeq::__('The star numbers 1, 13, 37, 73, 121, etc, 6*n*(n-1)+1, also called the centred 12-gonals.');
  1         2  
  1         3  
37 1     1   3 use constant default_i_start => 1;
  1         1  
  1         36  
38 1     1   4 use constant values_min => 1;
  1         1  
  1         31  
39 1     1   4 use constant characteristic_increasing => 1;
  1         1  
  1         34  
40 1     1   3 use constant characteristic_integer => 1;
  1         1  
  1         37  
41              
42             # cf
43             # A006060 - which are also triangular numbers
44             # A068774 - indices of the triangulars
45             # A068775 - indices of the stars
46             # A006061 - which are also perfect squares
47             # A054320 - indices of the squares
48             # A068778 - indices of the stars
49             #
50              
51             # centered polygonal numbers (k*n^2-k*n+2)/2, for k = 3 through 14 sides:
52             # A005448 , A001844 , A005891 , A003215 , A069099 , A016754 , A060544 ,
53             # A062786 , A069125 , A003154 , A069126 , A069127
54             #
55             # centered polygonal numbers (k*n^2-k*n+2)/2, for k = 15 through 20 sides:
56             # A069128 , A069129 , A069130 , A069131 , A069132 , A069133
57             #
58 1     1   4 use constant oeis_anum => 'A003154'; # star numbers
  1         1  
  1         275  
59              
60             sub _UNTESTED__seek_to_value {
61 0     0   0 my ($self, $value) = @_;
62 0         0 $self->{'i'} = $self->value_to_i_ceil($value);
63             }
64              
65             sub ith {
66 183     183 1 136 my ($self, $i) = @_;
67 183         264 return 6*$i*($i-1)+1;
68             }
69             sub pred {
70 246     246 1 549 my ($self, $value) = @_;
71 246 50       267 if ($value >= 0) {
72 246         168 my $int = int($value);
73 246 100       281 if ($value == $int) {
74 126         105 my $i = _inverse($int);
75 126         117 return ($int == $self->ith($i));
76             }
77             }
78 120         89 return 0;
79             }
80              
81             sub value_to_i {
82 28     28 1 62 my ($self, $value) = @_;
83 28 100       50 if ($value >= 0) {
84 25         488 my $int = int($value);
85 25 100       87 if ($value == $int) {
86 14         84 my $i = int(_inverse($int));
87 14 100       1868 if ($int == $self->ith($i)) {
88 10         1554 return $i;
89             }
90             }
91             }
92 18         17 return undef;
93             }
94             sub value_to_i_floor {
95 47     47 1 632 my ($self, $value) = @_;
96 47 100       60 if ($value < 0) { return 0; }
  9         10  
97 38         551 return int(_inverse(int($value)));
98             }
99             *value_to_i_estimate = \&value_to_i_floor;
100              
101             # i = 1/2 + sqrt(1/6 * $n + 1/12)
102             # = (3 + sqrt(6 * $n + 3)) / 6
103             #
104             sub _inverse {
105 178     178   158 my ($int) = @_;
106 178         208 return int ((sqrt(6*$int + 3) + 3) / 6);
107             }
108              
109             1;
110             __END__