File Coverage

blib/lib/Math/ModInt/BigInt.pm
Criterion Covered Total %
statement 78 78 100.0
branch 20 20 100.0
condition 6 6 100.0
subroutine 21 21 100.0
pod 2 2 100.0
total 127 127 100.0


line stmt bran cond sub pod time code
1             package Math::ModInt::BigInt;
2              
3 4     4   1532 use 5.006;
  4         16  
4 4     4   25 use strict;
  4         10  
  4         86  
5 4     4   17 use warnings;
  4         8  
  4         148  
6 4     4   26 use Carp qw(croak);
  4         7  
  4         296  
7 4     4   1360 use Math::BigInt;
  4         29334  
  4         33  
8 4     4   27745 use constant _ISSUE_CPAN_RT79060 => -1 != Math::BigInt->new(-2) / 3;
  4         12  
  4         29  
9              
10             # ----- object definition -----
11              
12             # Math::ModInt::BigInt=ARRAY(...)
13              
14             # .......... index .......... # .......... value ..........
15 4     4   3618 use constant F_RESIDUE => 0; # residue r, 0 <= r < m
  4         11  
  4         218  
16 4     4   69 use constant F_MODULUS => 1; # modulus m
  4         9  
  4         273  
17 4     4   25 use constant NFIELDS => 2;
  4         34  
  4         366  
18              
19             # ----- class data -----
20              
21             BEGIN {
22 4     4   30 require Math::ModInt;
23 4         115 our @ISA = 'Math::ModInt';
24 4         3106 our $VERSION = '0.013';
25             }
26              
27             # ----- overridden methods -----
28              
29             sub _NEG {
30 7     7   619 my ($this) = @_;
31 7         19 return $this->_NEW(-$this->residue);
32             }
33              
34             sub _ADD {
35 33     33   62 my ($this, $that) = @_;
36 33         80 return $this->_NEW($this->residue + $that->residue);
37             }
38              
39             sub _SUB {
40 25     25   46 my ($this, $that) = @_;
41 25         47 return $this->_NEW($this->residue - $that->residue);
42             }
43              
44             sub _MUL {
45 41     41   78 my ($this, $that) = @_;
46 41         93 return $this->_NEW($this->residue * $that->residue);
47             }
48              
49             sub _DIV {
50 25     25   46 my ($this, $that) = @_;
51 25         43 my $i = $that->residue->copy->bmodinv($that->modulus);
52 25 100       5748 return $this->undefined if $i->is_nan;
53 14         98 return $this->_NEW($this->residue * $i);
54             }
55              
56             sub _POW {
57 71     71   149 my ($this, $exp) = @_;
58 71 100       190 if ($this->is_zero) {
59             # work around Math::BigInt bug rt.cpan.org #61543
60 12 100       2062 return $this->undefined if 0 > $exp;
61 8 100       24 return $this->_NEW(1) if 0 == $exp;
62 6         18 return $this;
63             }
64 59         11203 my $p = $this->residue->copy->bmodpow($exp, $this->modulus);
65 59 100       69759 return $this->undefined if $p->is_nan;
66 57         493 return $this->_NEW($p);
67             }
68              
69             sub _INV {
70 7     7   13 my ($this) = @_;
71 7         17 my $i = $this->residue->copy->bmodinv($this->modulus);
72 7 100       1779 return $this->undefined if $i->is_nan;
73 4         28 return $this->_NEW($i);
74             }
75              
76             sub _NEW {
77 301     301   11728 my ($this, $int, $modulus) = @_;
78 301         470 my $class = ref $this;
79 301 100       559 if ($class) {
80 289         513 $modulus = $this->modulus;
81             }
82             else {
83 12         21 $class = $this;
84             }
85 301         576 foreach my $arg ($int, $modulus) {
86 602 100 100     6793 if (!ref($arg) || !$arg->isa('Math::BigInt')) {
87 90         221 $arg = Math::BigInt->new($arg);
88             }
89             }
90 301         1153 return bless [$int % $modulus, $modulus], $class;
91             }
92              
93             sub _NEW2 {
94 3     3   8 my ($this, $int, $modulus) = @_;
95 3         7 my $class = ref $this;
96 3 100       13 if ($class) {
97 2         6 $modulus = $this->modulus;
98             }
99             else {
100 1         3 $class = $this;
101             }
102 3         8 foreach my $arg ($int, $modulus) {
103 6 100 100     195 if (!ref($arg) || !$arg->isa('Math::BigInt')) {
104 2         7 $arg = Math::BigInt->new($arg);
105             }
106             }
107 3         8 my ($quotient, $remainder);
108 3         4 if (_ISSUE_CPAN_RT79060 && $int->is_neg) {
109             $remainder = $int % $modulus;
110             $quotient = ($int - $remainder) / $modulus;
111             }
112             else {
113 3         10 ($quotient, $remainder) = $int->copy->bdiv($modulus);
114             }
115 3         1455 return ($quotient, bless [$remainder, $modulus], $class);
116             }
117              
118             sub residue {
119 853     853 1 2584 my ($this) = @_;
120 853         2007 return $this->[F_RESIDUE];
121             }
122              
123             sub modulus {
124 1101     1101 1 12282 my ($this) = @_;
125 1101         2390 return $this->[F_MODULUS];
126             }
127              
128             1;
129              
130             __END__