File Coverage

blib/lib/Math/Polynomial/ModInt/Order.pm
Criterion Covered Total %
statement 83 83 100.0
branch 20 20 100.0
condition 33 33 100.0
subroutine 17 17 100.0
pod 7 7 100.0
total 160 160 100.0


line stmt bran cond sub pod time code
1             package Math::Polynomial::ModInt::Order;
2              
3 1     1   446 use strict;
  1         3  
  1         24  
4 1     1   4 use warnings;
  1         2  
  1         17  
5 1     1   429 use Readonly ();
  1         3100  
  1         61  
6              
7             BEGIN {
8 1     1   5 require Exporter;
9 1         14 our @ISA = qw(Exporter);
10 1         10 our @EXPORT_OK = qw($BY_INDEX $SPARSE $CONWAY);
11 1         3 our %EXPORT_TAGS = ( all => \@EXPORT_OK );
12 1         820 our $VERSION = '0.005';
13             }
14              
15 4     4 1 42 sub cmp { $_[0]->(@_[1, 2]) }
16 4     4 1 11 sub eq { $_[0]->(@_[1, 2]) == 0 }
17 4     4 1 11 sub ne { $_[0]->(@_[1, 2]) != 0 }
18 4     4 1 10 sub lt { $_[0]->(@_[1, 2]) < 0 }
19 4     4 1 10 sub le { $_[0]->(@_[1, 2]) <= 0 }
20 4     4 1 12 sub gt { $_[0]->(@_[1, 2]) > 0 }
21 4     4 1 12 sub ge { $_[0]->(@_[1, 2]) >= 0 }
22              
23             package Math::Polynomial::ModInt::Order::ByIndex;
24              
25             our @ISA = (Math::Polynomial::ModInt::Order::);
26             Readonly::Scalar
27             $Math::Polynomial::ModInt::Order::BY_INDEX => bless \&_compare;
28              
29             sub _compare ($$) {
30 165     165   249 my ($a, $b) = @_;
31 165         270 my $n = $a->degree;
32 165   100     622 my $result =
33             $a->modulus <=> $b->modulus ||
34             $n <=> $b->degree;
35 165   100     1165 while (!$result && $n >= 0) {
36 247         371 $result = $a->coeff($n)->residue <=> $b->coeff($n)->residue;
37 247         3328 --$n;
38             }
39 165         263 return $result;
40             }
41              
42             sub next_poly {
43 56     56   2108 my ($class, $poly, $i0) = @_;
44 56         89 my @coeff = $poly->coeff;
45 56         418 my $one = $poly->coeff_one;
46 56   100     196 my $i = $i0 || 0;
47             {
48 56 100       71 if ($i < @coeff) {
  84         576  
49 83 100       144 $coeff[$i++] += $one or redo;
50             }
51             else {
52 1         2 $coeff[$i] = $one;
53             }
54             }
55 56         974 return $poly->new(@coeff);
56             }
57              
58             package Math::Polynomial::ModInt::Order::Sparse;
59              
60             our @ISA = (Math::Polynomial::ModInt::Order::);
61             Readonly::Scalar
62             $Math::Polynomial::ModInt::Order::SPARSE => bless \&_compare;
63              
64             sub _compare ($$) {
65 111     111   197 my ($a, $b) = @_;
66 111   100     171 my $n = $a->proper_degree || 0;
67 111   100     805 my $result =
68             $a->modulus <=> $b->modulus ||
69             $a->degree <=> $b->degree ||
70             $a->coeff($n)->residue <=> $b->coeff($n)->residue ||
71             $a->number_of_terms <=> $b->number_of_terms;
72 111   100     815 while (!$result && --$n >= 0) {
73 136         1052 $result = $a->coeff($n)->residue <=> $b->coeff($n)->residue;
74             }
75 111         988 return $result;
76             }
77              
78             sub next_poly {
79 82     82   2759 my ($class, $poly) = @_;
80 82         126 my @coeff = $poly->coefficients;
81 82         1169 my $zero = $poly->coeff_zero;
82 82         230 my $one = $poly->coeff_one;
83 82         189 my $i = 0;
84 82         87 my $j = 0;
85 82   100     197 while ($i < $#coeff && $zero == $coeff[$i]) {
86 37         434 ++$i;
87             }
88 82   100     724 while ($i < $#coeff && $zero == ($coeff[$i] += $one)) {
89 48         881 ++$j;
90 48         95 ++$i;
91             }
92 82 100 100     1098 if ($i == $#coeff) {
    100          
93 21 100       29 if ($j < $i) {
94 12         15 ++$j;
95             }
96             else {
97 9         10 $j = 0;
98 9 100       17 if ($zero == ($coeff[$i] += $one)) {
99 4         71 $coeff[++$i] = $one;
100             }
101             }
102             }
103             elsif ($j && $one == $coeff[$i]) {
104 12         126 --$j;
105             }
106 82         318 while ($j > 0) {
107 36         58 $coeff[--$j] = $one;
108             }
109 82         155 return $poly->new(@coeff);
110             }
111              
112             package Math::Polynomial::ModInt::Order::Conway;
113              
114             our @ISA = (Math::Polynomial::ModInt::Order::);
115             Readonly::Scalar
116             $Math::Polynomial::ModInt::Order::CONWAY => bless \&_compare;
117              
118             sub _compare ($$) {
119 86     86   150 my ($a, $b) = @_;
120 86         121 my $n = $a->degree;
121 86         284 my $inv = 0;
122 86   100     135 my $result =
123             $a->modulus <=> $b->modulus ||
124             $n <=> $b->degree;
125 86   100     686 while (!$result && $n >= 0) {
126 234 100       411 $result =
127             $inv?
128             (-$a->coeff($n))->residue <=> (-$b->coeff($n))->residue:
129             ( $a->coeff($n))->residue <=> ( $b->coeff($n))->residue;
130 234         3296 --$n;
131 234         484 $inv ^= 1;
132             }
133 86         126 return $result;
134             }
135              
136             sub next_poly {
137 56     56   2925 my ($class, $poly, $i0) = @_;
138 56         93 my @coeff = $poly->coeff;
139 56         447 my $one = $poly->coeff_one;
140 56   100     207 my $i = $i0 || 0;
141 56 100       136 my $delta = 1 & (@coeff ^ $i)? $one: -$one;
142             {
143 56 100       163 if ($i < @coeff) {
  84         618  
144 83 100       148 $coeff[$i++] += $delta or $delta = -$delta, redo;
145             }
146             else {
147 1         2 $coeff[$i] = $one;
148             }
149             }
150 56         973 return $poly->new(@coeff);
151             }
152              
153             1;
154              
155             __END__