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   518 use strict;
  1         2  
  1         26  
4 1     1   4 use warnings;
  1         2  
  1         216  
5              
6             BEGIN {
7 1     1   7 require Exporter;
8 1         14 our @ISA = qw(Exporter);
9 1         4 our @EXPORT_OK = qw($BY_INDEX $SPARSE $CONWAY);
10 1         2 our %EXPORT_TAGS = ( all => \@EXPORT_OK );
11 1         927 our $VERSION = '0.002';
12             }
13              
14 4     4 1 36 sub cmp { $_[0]->(@_[1, 2]) }
15 4     4 1 10 sub eq { $_[0]->(@_[1, 2]) == 0 }
16 4     4 1 10 sub ne { $_[0]->(@_[1, 2]) != 0 }
17 4     4 1 10 sub lt { $_[0]->(@_[1, 2]) < 0 }
18 4     4 1 11 sub le { $_[0]->(@_[1, 2]) <= 0 }
19 4     4 1 13 sub gt { $_[0]->(@_[1, 2]) > 0 }
20 4     4 1 9 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   256 my ($a, $b) = @_;
29 165         254 my $n = $a->degree;
30 165   100     650 my $result =
31             $a->modulus <=> $b->modulus ||
32             $n <=> $b->degree;
33 165   100     1161 while (!$result && $n >= 0) {
34 247         399 $result = $a->coeff($n)->residue <=> $b->coeff($n)->residue;
35 247         4155 --$n;
36             }
37 165         297 return $result;
38             }
39              
40             sub next_poly {
41 55     55   1319 my ($class, $poly) = @_;
42 55         82 my @coeff = $poly->coeff;
43 55         413 my $one = $poly->coeff_one;
44 55         127 my $i = 0;
45             {
46 55 100       60 if ($i < @coeff) {
  83         575  
47 82 100       133 $coeff[$i++] += $one or redo;
48             }
49             else {
50 1         3 $coeff[$i] = $one;
51             }
52             }
53 55         963 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   191 my ($a, $b) = @_;
63 111   100     179 my $n = $a->proper_degree || 0;
64 111   100     814 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     833 while (!$result && --$n >= 0) {
70 136         1077 $result = $a->coeff($n)->residue <=> $b->coeff($n)->residue;
71             }
72 111         1046 return $result;
73             }
74              
75             sub next_poly {
76 82     82   2782 my ($class, $poly) = @_;
77 82         131 my @coeff = $poly->coefficients;
78 82         1207 my $zero = $poly->coeff_zero;
79 82         228 my $one = $poly->coeff_one;
80 82         191 my $i = 0;
81 82         90 my $j = 0;
82 82   100     228 while ($i < $#coeff && $zero == $coeff[$i]) {
83 37         450 ++$i;
84             }
85 82   100     791 while ($i < $#coeff && $zero == ($coeff[$i] += $one)) {
86 48         902 ++$j;
87 48         101 ++$i;
88             }
89 82 100 100     1174 if ($i == $#coeff) {
    100          
90 21 100       41 if ($j < $i) {
91 12         14 ++$j;
92             }
93             else {
94 9         12 $j = 0;
95 9 100       21 if ($zero == ($coeff[$i] += $one)) {
96 4         83 $coeff[++$i] = $one;
97             }
98             }
99             }
100             elsif ($j && $one == $coeff[$i]) {
101 12         127 --$j;
102             }
103 82         311 while ($j > 0) {
104 36         63 $coeff[--$j] = $one;
105             }
106 82         160 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   161 my ($a, $b) = @_;
116 86         132 my $n = $a->degree;
117 86         293 my $inv = 0;
118 86   100     127 my $result =
119             $a->modulus <=> $b->modulus ||
120             $n <=> $b->degree;
121 86   100     672 while (!$result && $n >= 0) {
122 234 100       439 $result =
123             $inv?
124             (-$a->coeff($n))->residue <=> (-$b->coeff($n))->residue:
125             ( $a->coeff($n))->residue <=> ( $b->coeff($n))->residue;
126 234         3673 --$n;
127 234         506 $inv ^= 1;
128             }
129 86         129 return $result;
130             }
131              
132             sub next_poly {
133 55     55   2358 my ($class, $poly) = @_;
134 55         120 my @coeff = $poly->coeff;
135 55         386 my $one = $poly->coeff_one;
136 55 100       203 my $delta = 1 & @coeff? $one: -$one;
137 55         151 my $i = 0;
138             {
139 55 100       63 if ($i < @coeff) {
  83         609  
140 82 100       146 $coeff[$i++] += $delta or $delta = -$delta, redo;
141             }
142             else {
143 1         2 $coeff[$i] = $one;
144             }
145             }
146 55         987 return $poly->new(@coeff);
147             }
148              
149             1;
150              
151             __END__