File Coverage

blib/lib/Math/Polynomial/ModInt/Order.pm
Criterion Covered Total %
statement 80 80 100.0
branch 20 20 100.0
condition 29 29 100.0
subroutine 16 16 100.0
pod 7 7 100.0
total 152 152 100.0


line stmt bran cond sub pod time code
1             package Math::Polynomial::ModInt::Order;
2              
3 1     1   514 use strict;
  1         2  
  1         26  
4 1     1   4 use warnings;
  1         2  
  1         82  
5              
6             BEGIN {
7 1     1   5 require Exporter;
8 1         14 our @ISA = qw(Exporter);
9 1         3 our @EXPORT_OK = qw($BY_INDEX $SPARSE $CONWAY);
10 1         2 our %EXPORT_TAGS = ( all => \@EXPORT_OK );
11 1         872 our $VERSION = '0.004';
12             }
13              
14 4     4 1 34 sub cmp { $_[0]->(@_[1, 2]) }
15 4     4 1 11 sub eq { $_[0]->(@_[1, 2]) == 0 }
16 4     4 1 11 sub ne { $_[0]->(@_[1, 2]) != 0 }
17 4     4 1 27 sub lt { $_[0]->(@_[1, 2]) < 0 }
18 4     4 1 10 sub le { $_[0]->(@_[1, 2]) <= 0 }
19 4     4 1 12 sub gt { $_[0]->(@_[1, 2]) > 0 }
20 4     4 1 10 sub ge { $_[0]->(@_[1, 2]) >= 0 }
21              
22             package Math::Polynomial::ModInt::Order::ByIndex;
23              
24             our @ISA = (Math::Polynomial::ModInt::Order::);
25             $Math::Polynomial::ModInt::Order::BY_INDEX = bless \&_compare;
26              
27             sub _compare ($$) {
28 165     165   247 my ($a, $b) = @_;
29 165         260 my $n = $a->degree;
30 165   100     635 my $result =
31             $a->modulus <=> $b->modulus ||
32             $n <=> $b->degree;
33 165   100     1159 while (!$result && $n >= 0) {
34 247         355 $result = $a->coeff($n)->residue <=> $b->coeff($n)->residue;
35 247         3301 --$n;
36             }
37 165         270 return $result;
38             }
39              
40             sub next_poly {
41 55     55   1310 my ($class, $poly) = @_;
42 55         88 my @coeff = $poly->coeff;
43 55         416 my $one = $poly->coeff_one;
44 55         140 my $i = 0;
45             {
46 55 100       66 if ($i < @coeff) {
  83         561  
47 82 100       141 $coeff[$i++] += $one or redo;
48             }
49             else {
50 1         3 $coeff[$i] = $one;
51             }
52             }
53 55         978 return $poly->new(@coeff);
54             }
55              
56             package Math::Polynomial::ModInt::Order::Sparse;
57              
58             our @ISA = (Math::Polynomial::ModInt::Order::);
59             $Math::Polynomial::ModInt::Order::SPARSE = bless \&_compare;
60              
61             sub _compare ($$) {
62 111     111   184 my ($a, $b) = @_;
63 111   100     170 my $n = $a->proper_degree || 0;
64 111   100     834 my $result =
65             $a->modulus <=> $b->modulus ||
66             $a->degree <=> $b->degree ||
67             $a->coeff($n)->residue <=> $b->coeff($n)->residue ||
68             $a->number_of_terms <=> $b->number_of_terms;
69 111   100     850 while (!$result && --$n >= 0) {
70 136         1037 $result = $a->coeff($n)->residue <=> $b->coeff($n)->residue;
71             }
72 111         978 return $result;
73             }
74              
75             sub next_poly {
76 82     82   2826 my ($class, $poly) = @_;
77 82         132 my @coeff = $poly->coefficients;
78 82         1198 my $zero = $poly->coeff_zero;
79 82         217 my $one = $poly->coeff_one;
80 82         185 my $i = 0;
81 82         116 my $j = 0;
82 82   100     193 while ($i < $#coeff && $zero == $coeff[$i]) {
83 37         456 ++$i;
84             }
85 82   100     738 while ($i < $#coeff && $zero == ($coeff[$i] += $one)) {
86 48         870 ++$j;
87 48         95 ++$i;
88             }
89 82 100 100     1147 if ($i == $#coeff) {
    100          
90 21 100       52 if ($j < $i) {
91 12         13 ++$j;
92             }
93             else {
94 9         12 $j = 0;
95 9 100       19 if ($zero == ($coeff[$i] += $one)) {
96 4         73 $coeff[++$i] = $one;
97             }
98             }
99             }
100             elsif ($j && $one == $coeff[$i]) {
101 12         138 --$j;
102             }
103 82         310 while ($j > 0) {
104 36         64 $coeff[--$j] = $one;
105             }
106 82         145 return $poly->new(@coeff);
107             }
108              
109             package Math::Polynomial::ModInt::Order::Conway;
110              
111             our @ISA = (Math::Polynomial::ModInt::Order::);
112             $Math::Polynomial::ModInt::Order::CONWAY = bless \&_compare;
113              
114             sub _compare ($$) {
115 86     86   144 my ($a, $b) = @_;
116 86         136 my $n = $a->degree;
117 86         280 my $inv = 0;
118 86   100     137 my $result =
119             $a->modulus <=> $b->modulus ||
120             $n <=> $b->degree;
121 86   100     687 while (!$result && $n >= 0) {
122 234 100       384 $result =
123             $inv?
124             (-$a->coeff($n))->residue <=> (-$b->coeff($n))->residue:
125             ( $a->coeff($n))->residue <=> ( $b->coeff($n))->residue;
126 234         3301 --$n;
127 234         495 $inv ^= 1;
128             }
129 86         119 return $result;
130             }
131              
132             sub next_poly {
133 55     55   2170 my ($class, $poly) = @_;
134 55         95 my @coeff = $poly->coeff;
135 55         395 my $one = $poly->coeff_one;
136 55 100       211 my $delta = 1 & @coeff? $one: -$one;
137 55         158 my $i = 0;
138             {
139 55 100       64 if ($i < @coeff) {
  83         606  
140 82 100       143 $coeff[$i++] += $delta or $delta = -$delta, redo;
141             }
142             else {
143 1         2 $coeff[$i] = $one;
144             }
145             }
146 55         981 return $poly->new(@coeff);
147             }
148              
149             1;
150              
151             __END__